@promptbook/cli 0.114.0-14 → 0.114.0-19
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/apps/agents-server/next.config.ts +6 -0
- package/apps/agents-server/src/app/admin/_components/AdminFilterFields.tsx +84 -0
- package/apps/agents-server/src/app/admin/_components/AdminMetricCard.tsx +36 -0
- package/apps/agents-server/src/app/admin/_components/AdminTaskManagerTabs.tsx +97 -0
- package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerClient.tsx +103 -0
- package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerEditDialog.tsx +232 -0
- package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerFiltersCard.tsx +195 -0
- package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerRow.tsx +189 -0
- package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerSummaryMetrics.tsx +60 -0
- package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerTableCard.tsx +147 -0
- package/apps/agents-server/src/app/admin/planned-messages/page.tsx +17 -0
- package/apps/agents-server/src/app/admin/planned-messages/plannedMessageEditForm.ts +186 -0
- package/apps/agents-server/src/app/admin/planned-messages/plannedMessageManagerDialogs.ts +46 -0
- package/apps/agents-server/src/app/admin/planned-messages/plannedMessageManagerPresentation.tsx +188 -0
- package/apps/agents-server/src/app/admin/planned-messages/resolvePlannedMessageSortValue.ts +115 -0
- package/apps/agents-server/src/app/admin/planned-messages/usePlannedMessageManagerData.ts +116 -0
- package/apps/agents-server/src/app/admin/planned-messages/usePlannedMessageManagerState.ts +289 -0
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerClient.tsx +7 -2
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerFiltersCard.tsx +7 -73
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerSummaryMetrics.tsx +5 -30
- package/apps/agents-server/src/app/admin/task-manager/[taskId]/TaskManagerTaskDetailClient.tsx +1 -1
- package/apps/agents-server/src/app/agents/[agentName]/api/book/reference-diagnostics/route.ts +30 -7
- package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +1 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/book/test.http +3 -3
- package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorMissingReferences.tsx +106 -12
- package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +3 -0
- package/apps/agents-server/src/app/agents/[agentName]/book/useBookEditorDiagnostics.ts +12 -0
- package/apps/agents-server/src/app/agents/[agentName]/book/useBookEditorWrapper.tsx +2 -0
- package/apps/agents-server/src/app/agents/[agentName]/chat/AgentGoalChatPlannedMessages.tsx +46 -3
- package/apps/agents-server/src/app/api/admin/default-agents/reinstate/route.ts +5 -1
- package/apps/agents-server/src/app/api/admin/planned-messages/[timeoutId]/route.ts +80 -0
- package/apps/agents-server/src/app/api/admin/planned-messages/route.ts +19 -0
- package/apps/agents-server/src/app/api/internal/agent-goal-chat-planned-messages/route.ts +30 -2
- package/apps/agents-server/src/components/DefaultAgents/ReinstateBundledAgentsButton.tsx +7 -0
- package/apps/agents-server/src/components/DefaultAgents/coreAgentsAdminRoute.ts +6 -0
- package/apps/agents-server/src/components/Header/buildHeaderSystemMenuItems.ts +7 -0
- package/apps/agents-server/src/components/Homepage/DefaultAgentsStatusNotice.tsx +1 -7
- package/apps/agents-server/src/database/migrations/2026-08-1800-user-chat-timeout-schedule.sql +11 -0
- package/apps/agents-server/src/instrumentation-node.ts +18 -0
- package/apps/agents-server/src/languages/ServerTranslationKeys.ts +4 -0
- package/apps/agents-server/src/languages/translations/czech.yaml +4 -0
- package/apps/agents-server/src/languages/translations/english.yaml +4 -0
- package/apps/agents-server/src/tools/agentGoalChatTimeoutToolFunctions.ts +62 -15
- package/apps/agents-server/src/tools/agentGoalChatTimeoutTools.ts +63 -9
- package/apps/agents-server/src/utils/adminEntityLookups/loadAgentNamesByPermanentId.ts +45 -0
- package/apps/agents-server/src/utils/adminEntityLookups/loadUsernamesByUserId.ts +36 -0
- package/apps/agents-server/src/utils/adminEntityLookups.ts +2 -0
- package/apps/agents-server/src/utils/agentGoalChat/agentGoalChatPlannedMessageActions.ts +299 -52
- package/apps/agents-server/src/utils/agentGoalChat/createAgentGoalChatNoteContent.ts +45 -17
- package/apps/agents-server/src/utils/agentGoalChat.ts +1 -0
- package/apps/agents-server/src/utils/agentProjects/agentProjectIdentity.ts +46 -0
- package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeAutostartScheduler.ts +162 -0
- package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeDesiredState.ts +252 -0
- package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeDisplay.ts +6 -3
- package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeDomains.ts +2 -44
- package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimePaths.ts +25 -0
- package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimePm2.ts +4 -3
- package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeRegistry.ts +77 -24
- package/apps/agents-server/src/utils/agentProjects/agentProjectStateMutationQueue.ts +58 -0
- package/apps/agents-server/src/utils/agentProjects/listAllLocalAgentProjectIdentities.ts +48 -0
- package/apps/agents-server/src/utils/agentProjects/resolveAgentProjectRuntimeEnvironmentFlag.ts +23 -0
- package/apps/agents-server/src/utils/agentProjects/resolveAgentProjectRuntimeStatus.ts +73 -0
- package/apps/agents-server/src/utils/agentProjects/startDefaultAgentProjectRuntimes.ts +110 -0
- package/apps/agents-server/src/utils/agentReferenceResolver/MissingCoreAgentRecovery.ts +19 -0
- package/apps/agents-server/src/utils/agentReferenceResolver/bookScopedAgentReferences.ts +7 -0
- package/apps/agents-server/src/utils/agentReferenceResolver/createAgentInheritanceDiagnostics.ts +457 -0
- package/apps/agents-server/src/utils/agentReferenceResolver/createUnresolvedAgentReferenceDiagnostics.ts +27 -0
- package/apps/agents-server/src/utils/agentReferenceResolver/resolveCoreAgentAwareMissingReferences.ts +156 -0
- package/apps/agents-server/src/utils/chatMessageChips/createAnsweredMessageChipToolCalls.ts +15 -3
- package/apps/agents-server/src/utils/chatMessageChips/createPlannedMessageChipToolCalls.ts +8 -3
- package/apps/agents-server/src/utils/chatMessageChips/createTouchedExternalSourceChipToolCalls.ts +39 -0
- package/apps/agents-server/src/utils/chatMessageChips/createTouchedProjectChipResult.ts +45 -0
- package/apps/agents-server/src/utils/chatMessageChips/createTouchedProjectChipToolCalls.ts +58 -24
- package/apps/agents-server/src/utils/cronExpression/CronExpression.ts +63 -0
- package/apps/agents-server/src/utils/cronExpression/normalizeCronExpression.ts +34 -0
- package/apps/agents-server/src/utils/cronExpression/normalizeCronExpressionWhitespace.ts +11 -0
- package/apps/agents-server/src/utils/cronExpression/parseCronExpression.ts +41 -0
- package/apps/agents-server/src/utils/cronExpression/parseCronExpressionField.ts +140 -0
- package/apps/agents-server/src/utils/cronExpression/resolveNextCronRun.ts +100 -0
- package/apps/agents-server/src/utils/cronExpression/throwInvalidCronExpressionField.ts +20 -0
- package/apps/agents-server/src/utils/cronExpression.ts +10 -0
- package/apps/agents-server/src/utils/explicitFromCommitment.ts +130 -0
- package/apps/agents-server/src/utils/getAdminChatTasksResponse/getAdminChatTasks/loadAdminChatTaskFallbackData.ts +3 -77
- package/apps/agents-server/src/utils/localChatRunner/applyLocalAgentPlannedMessageCommands.ts +53 -4
- package/apps/agents-server/src/utils/localChatRunner/prepareLocalAgentPlannedMessagesSidecar.ts +15 -7
- package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +8 -0
- package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentBooks.ts +5 -11
- package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentRuntime.ts +2 -2
- package/apps/agents-server/src/utils/managementApi/managementApiSchemas.ts +2 -2
- package/apps/agents-server/src/utils/plannedMessageManager/cancelManagedPlannedMessage.ts +35 -0
- package/apps/agents-server/src/utils/plannedMessageManager/collectPlannedMessageAgentOptions.ts +56 -0
- package/apps/agents-server/src/utils/plannedMessageManager/createPlannedMessageManagerCounters.ts +104 -0
- package/apps/agents-server/src/utils/plannedMessageManager/filterPlannedMessages.ts +191 -0
- package/apps/agents-server/src/utils/plannedMessageManager/getPlannedMessageManagerResponse.ts +55 -0
- package/apps/agents-server/src/utils/plannedMessageManager/isPlannedMessageStillPlanned.ts +18 -0
- package/apps/agents-server/src/utils/plannedMessageManager/loadPlannedMessageManagerRecord.ts +32 -0
- package/apps/agents-server/src/utils/plannedMessageManager/mapPlannedMessageManagerRecord.ts +73 -0
- package/apps/agents-server/src/utils/plannedMessageManager/parsePlannedMessageManagerUpdateRequest.ts +76 -0
- package/apps/agents-server/src/utils/plannedMessageManager/resolvePlannedMessageEndReason.ts +59 -0
- package/apps/agents-server/src/utils/plannedMessageManager/resolvePlannedMessageLifecycle.ts +99 -0
- package/apps/agents-server/src/utils/plannedMessageManager/resolvePlannedMessageRecurrenceKind.ts +40 -0
- package/apps/agents-server/src/utils/plannedMessageManager/updateManagedPlannedMessage.ts +121 -0
- package/apps/agents-server/src/utils/plannedMessagesAdmin.ts +200 -0
- package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +114 -95
- package/apps/agents-server/src/utils/userChatClient.ts +4 -0
- package/apps/agents-server/src/utils/userChatTimeout/UserChatTimeoutRecord.ts +37 -1
- package/apps/agents-server/src/utils/userChatTimeout/agentScopedTimeoutBulkActions.ts +11 -17
- package/apps/agents-server/src/utils/userChatTimeout/createTimeoutWakeUpMessage.ts +37 -13
- package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/PlannedMessageSchedule.ts +52 -0
- package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/hasPlannedMessageRecurrence.ts +13 -0
- package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/isPlannedMessageScheduleFinished.ts +30 -0
- package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/normalizePlannedMessageScheduleValues.ts +62 -0
- package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/parsePlannedMessageSchedule.ts +202 -0
- package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/resolvePlannedMessageDueAt.ts +121 -0
- package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule.ts +12 -0
- package/apps/agents-server/src/utils/userChatTimeout/setAgentScopedUserChatTimeoutPausedState.ts +66 -0
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/createUserChatTimeout.ts +76 -5
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/listAllUserChatTimeouts.ts +37 -0
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/mapUserChatTimeoutRow.ts +9 -0
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/repeatFiredUserChatTimeout.ts +19 -9
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/updateAgentScopedUserChatTimeout.ts +39 -6
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore.ts +1 -0
- package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutWorker.ts +110 -11
- package/apps/agents-server/src/utils/userChatTimeout.ts +16 -0
- package/apps/agents-server/src/utils/vpsSelfUpdate/vpsSelfUpdateCron.ts +23 -316
- package/apps/agents-server/tests/e2e/support/AgentManagementApi.ts +3 -3
- package/esm/index.es.js +814 -58
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-agent-messages/git/commitAgentProjectChanges.d.ts +15 -0
- package/esm/scripts/run-agent-messages/git/commitAnsweredMessageProjectChanges.d.ts +24 -0
- package/esm/scripts/run-agent-messages/git/ensureAgentProjectGitRepository.d.ts +20 -0
- package/esm/scripts/run-agent-messages/git/readAgentProjectCommitChange.d.ts +11 -0
- package/esm/scripts/run-agent-messages/git/runAgentProjectGitCommand.d.ts +29 -0
- package/esm/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +3 -3
- package/esm/scripts/run-agent-messages/messages/listAgentProjectDirectoryNames.d.ts +7 -0
- package/esm/scripts/run-agent-messages/messages/resolveAnsweredMessageTouches.d.ts +29 -0
- package/esm/src/book-3.0/AgentMessageRunReport.d.ts +18 -0
- package/esm/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +38 -5
- package/esm/src/book-3.0/describeAgentPlannedMessageSchedule.d.ts +31 -0
- package/esm/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +1 -9
- package/esm/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.d.ts +28 -0
- package/esm/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.test.d.ts +1 -0
- package/esm/src/book-components/Chat/Chat/renderAgentProjectDiff.d.ts +13 -0
- package/esm/src/book-components/Chat/Chat/renderAgentProjectToolCallDetails.d.ts +16 -0
- package/esm/src/book-components/Chat/utils/agentProjectToolCall.d.ts +39 -0
- package/esm/src/book-components/Chat/utils/agentProjectToolCall.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/externalSourceToolCall.d.ts +38 -0
- package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +6 -0
- package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +15 -0
- package/esm/src/utils/agent-message-runtime/AgentMessageProjectChange.d.ts +76 -0
- package/esm/src/utils/agent-message-runtime/AgentMessageTouchedExternalSource.d.ts +45 -0
- package/esm/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +3 -0
- package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.d.ts +18 -0
- package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.test.d.ts +1 -0
- package/esm/src/utils/random/$generateBookBoilerplate.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/book-2.0/agent-source/string_book.ts +1 -1
- package/src/book-2.0/book-language-documentation/czechBookLanguageManualDictionary.ts +6 -1
- package/src/book-2.0/book-language-documentation/englishBookLanguageManualDictionary.ts +6 -1
- package/src/book-3.0/AgentMessageRunReport.ts +59 -0
- package/src/book-3.0/AgentPlannedMessagesSidecar.ts +64 -9
- package/src/book-3.0/describeAgentPlannedMessageSchedule.ts +94 -0
- package/src/book-components/BookEditor/BookEditorMonaco.tsx +2 -0
- package/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.ts +3 -11
- package/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.ts +71 -0
- package/src/book-components/Chat/Chat/Chat.module.css +165 -18
- package/src/book-components/Chat/Chat/ChatMessageMap.tsx +0 -1
- package/src/book-components/Chat/Chat/renderAgentProjectDiff.tsx +85 -0
- package/src/book-components/Chat/Chat/renderAgentProjectToolCallDetails.tsx +206 -0
- package/src/book-components/Chat/Chat/renderToolCallDetails.tsx +8 -0
- package/src/book-components/Chat/MarkdownContent/MarkdownContent.tsx +2 -3
- package/src/book-components/Chat/utils/agentProjectToolCall.ts +82 -5
- package/src/book-components/Chat/utils/externalSourceToolCall.ts +65 -0
- package/src/book-components/Chat/utils/getToolCallChipletInfo.ts +36 -0
- package/src/book-components/Chat/utils/renderMarkdown.ts +3 -10
- package/src/book-components/Chat/utils/timeoutToolCallPresentation.ts +12 -1
- package/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.ts +3 -1
- package/src/cli/cli-commands/common/harness/$checkHarnessInstallation.ts +3 -1
- package/src/cli/cli-commands/common/harnessUpdateCliOptions.ts +1 -4
- package/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.ts +47 -3
- package/src/commands/FORMAT/formatCommandParser.ts +4 -2
- package/src/commitments/FROM/FROM.ts +13 -0
- package/src/other/templates/getTemplatesPipelineCollection.ts +682 -912
- package/src/utils/agent-message-runtime/AgentMessageProjectChange.ts +183 -0
- package/src/utils/agent-message-runtime/AgentMessageTouchedExternalSource.ts +80 -0
- package/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.ts +3 -0
- package/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.ts +2 -4
- package/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.ts +341 -0
- package/src/utils/random/$generateBookBoilerplate.ts +1 -1
- package/src/version.ts +2 -2
- package/src/versions.txt +5 -0
- package/umd/index.umd.js +813 -57
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-agent-messages/git/commitAgentProjectChanges.d.ts +15 -0
- package/umd/scripts/run-agent-messages/git/commitAnsweredMessageProjectChanges.d.ts +24 -0
- package/umd/scripts/run-agent-messages/git/ensureAgentProjectGitRepository.d.ts +20 -0
- package/umd/scripts/run-agent-messages/git/readAgentProjectCommitChange.d.ts +11 -0
- package/umd/scripts/run-agent-messages/git/runAgentProjectGitCommand.d.ts +29 -0
- package/umd/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +3 -3
- package/umd/scripts/run-agent-messages/messages/listAgentProjectDirectoryNames.d.ts +7 -0
- package/umd/scripts/run-agent-messages/messages/resolveAnsweredMessageTouches.d.ts +29 -0
- package/umd/src/book-3.0/AgentMessageRunReport.d.ts +18 -0
- package/umd/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +38 -5
- package/umd/src/book-3.0/describeAgentPlannedMessageSchedule.d.ts +31 -0
- package/umd/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +1 -9
- package/umd/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.d.ts +28 -0
- package/umd/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.test.d.ts +1 -0
- package/umd/src/book-components/Chat/Chat/renderAgentProjectDiff.d.ts +13 -0
- package/umd/src/book-components/Chat/Chat/renderAgentProjectToolCallDetails.d.ts +16 -0
- package/umd/src/book-components/Chat/utils/agentProjectToolCall.d.ts +39 -0
- package/umd/src/book-components/Chat/utils/agentProjectToolCall.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/externalSourceToolCall.d.ts +38 -0
- package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +6 -0
- package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +15 -0
- package/umd/src/utils/agent-message-runtime/AgentMessageProjectChange.d.ts +76 -0
- package/umd/src/utils/agent-message-runtime/AgentMessageTouchedExternalSource.d.ts +45 -0
- package/umd/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +3 -0
- package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.d.ts +18 -0
- package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.test.d.ts +1 -0
- package/umd/src/utils/random/$generateBookBoilerplate.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
- package/apps/agents-server/src/app/admin/task-manager/TaskManagerScopeTabs.tsx +0 -74
- package/esm/scripts/run-agent-messages/messages/resolveTouchedAgentProjects.d.ts +0 -15
- package/umd/scripts/run-agent-messages/messages/resolveTouchedAgentProjects.d.ts +0 -15
package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerFiltersCard.tsx
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { resolvePlannedMessageAgentOptionLabel } from '@/src/utils/plannedMessageManager/collectPlannedMessageAgentOptions';
|
|
4
|
+
import { resolvePlannedMessageManagerViewCount } from '@/src/utils/plannedMessageManager/createPlannedMessageManagerCounters';
|
|
5
|
+
import type { PlannedMessageManagerView } from '@/src/utils/plannedMessagesAdmin';
|
|
6
|
+
import { Card } from '../../../components/Homepage/Card';
|
|
7
|
+
import { AdminFilterField, AdminFilterSelectField, type AdminFilterSelectOption } from '../_components/AdminFilterFields';
|
|
8
|
+
import { ANY_PLANNED_MESSAGE_FILTER_VALUE, type UsePlannedMessageManagerStateResult } from './usePlannedMessageManagerState';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* One view offered by the planned-message manager.
|
|
12
|
+
*
|
|
13
|
+
* @private function of PlannedMessageManagerFiltersCard
|
|
14
|
+
*/
|
|
15
|
+
type PlannedMessageViewOption = {
|
|
16
|
+
readonly id: PlannedMessageManagerView;
|
|
17
|
+
readonly label: string;
|
|
18
|
+
readonly description: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Views offered by the planned-message manager, in the order a plan moves through them.
|
|
23
|
+
*
|
|
24
|
+
* @private function of PlannedMessageManagerFiltersCard
|
|
25
|
+
*/
|
|
26
|
+
const PLANNED_MESSAGE_VIEW_OPTIONS: ReadonlyArray<PlannedMessageViewOption> = [
|
|
27
|
+
{ id: 'active', label: 'Active', description: 'Everything still planned' },
|
|
28
|
+
{ id: 'scheduled', label: 'Scheduled', description: 'Wake-up ahead' },
|
|
29
|
+
{ id: 'not-started', label: 'Not started', description: 'Starts later' },
|
|
30
|
+
{ id: 'ongoing', label: 'Ongoing', description: 'Waking an agent now' },
|
|
31
|
+
{ id: 'paused', label: 'Paused', description: 'Held back' },
|
|
32
|
+
{ id: 'finished', label: 'Finished', description: 'Cancelled or over' },
|
|
33
|
+
{ id: 'all', label: 'All', description: 'Whole history' },
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Frequency filter options.
|
|
38
|
+
*
|
|
39
|
+
* @private function of PlannedMessageManagerFiltersCard
|
|
40
|
+
*/
|
|
41
|
+
const PLANNED_MESSAGE_RECURRENCE_OPTIONS: ReadonlyArray<AdminFilterSelectOption> = [
|
|
42
|
+
{ value: ANY_PLANNED_MESSAGE_FILTER_VALUE, label: 'Any frequency' },
|
|
43
|
+
{ value: 'INTERVAL', label: 'Repeats on an interval' },
|
|
44
|
+
{ value: 'CRON', label: 'Repeats on a cron' },
|
|
45
|
+
{ value: 'ONCE', label: 'Wakes up once' },
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Last-run filter options.
|
|
50
|
+
*
|
|
51
|
+
* @private function of PlannedMessageManagerFiltersCard
|
|
52
|
+
*/
|
|
53
|
+
const PLANNED_MESSAGE_LAST_RUN_OPTIONS: ReadonlyArray<AdminFilterSelectOption> = [
|
|
54
|
+
{ value: ANY_PLANNED_MESSAGE_FILTER_VALUE, label: 'Any last run' },
|
|
55
|
+
{ value: 'never', label: 'Never ran' },
|
|
56
|
+
{ value: 'hour', label: 'Last hour' },
|
|
57
|
+
{ value: 'day', label: 'Last 24 hours' },
|
|
58
|
+
{ value: 'week', label: 'Last 7 days' },
|
|
59
|
+
{ value: 'older', label: 'Older than 7 days' },
|
|
60
|
+
];
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Page-size options.
|
|
64
|
+
*
|
|
65
|
+
* @private function of PlannedMessageManagerFiltersCard
|
|
66
|
+
*/
|
|
67
|
+
const PLANNED_MESSAGE_PAGE_SIZE_OPTIONS: ReadonlyArray<AdminFilterSelectOption> = [
|
|
68
|
+
{ value: '25', label: '25' },
|
|
69
|
+
{ value: '50', label: '50' },
|
|
70
|
+
{ value: '100', label: '100' },
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Auto-refresh presets.
|
|
75
|
+
*
|
|
76
|
+
* @private function of PlannedMessageManagerFiltersCard
|
|
77
|
+
*/
|
|
78
|
+
const PLANNED_MESSAGE_POLL_INTERVAL_OPTIONS: ReadonlyArray<AdminFilterSelectOption> = [
|
|
79
|
+
{ value: '5000', label: '5s' },
|
|
80
|
+
{ value: '10000', label: '10s' },
|
|
81
|
+
{ value: '30000', label: '30s' },
|
|
82
|
+
{ value: '0', label: 'Off' },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Props for the planned-message filter card.
|
|
87
|
+
*
|
|
88
|
+
* @private function of PlannedMessageManagerClient
|
|
89
|
+
*/
|
|
90
|
+
type PlannedMessageManagerFiltersCardProps = {
|
|
91
|
+
readonly state: UsePlannedMessageManagerStateResult;
|
|
92
|
+
readonly lastRefreshedLabel: string;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Renders the planned-message views and the parameters the listing is narrowed by.
|
|
97
|
+
*
|
|
98
|
+
* @private function of PlannedMessageManagerClient
|
|
99
|
+
*/
|
|
100
|
+
export function PlannedMessageManagerFiltersCard({ state, lastRefreshedLabel }: PlannedMessageManagerFiltersCardProps) {
|
|
101
|
+
const agentSelectOptions: ReadonlyArray<AdminFilterSelectOption> = [
|
|
102
|
+
{ value: ANY_PLANNED_MESSAGE_FILTER_VALUE, label: 'Every agent' },
|
|
103
|
+
...state.agentOptions.map((agentOption) => ({
|
|
104
|
+
value: agentOption.agentPermanentId,
|
|
105
|
+
label: `${resolvePlannedMessageAgentOptionLabel(agentOption)} (${agentOption.plannedMessageCount})`,
|
|
106
|
+
})),
|
|
107
|
+
];
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<Card className="hover:border-gray-200 hover:shadow-md">
|
|
111
|
+
<div className="flex flex-col gap-4">
|
|
112
|
+
<div className="flex flex-wrap gap-2">
|
|
113
|
+
{PLANNED_MESSAGE_VIEW_OPTIONS.map((viewOption) => (
|
|
114
|
+
<button
|
|
115
|
+
key={viewOption.id}
|
|
116
|
+
type="button"
|
|
117
|
+
onClick={() => state.selectView(viewOption.id)}
|
|
118
|
+
className={`rounded-xl border px-4 py-2 text-left transition ${
|
|
119
|
+
viewOption.id === state.filters.view
|
|
120
|
+
? 'border-blue-500 bg-blue-50 text-blue-700 shadow-sm'
|
|
121
|
+
: 'border-gray-200 bg-white text-gray-700 hover:border-gray-300 hover:bg-gray-50'
|
|
122
|
+
}`}
|
|
123
|
+
>
|
|
124
|
+
<div className="text-sm font-semibold">
|
|
125
|
+
{viewOption.label} ({resolvePlannedMessageManagerViewCount(state.counters, viewOption.id)})
|
|
126
|
+
</div>
|
|
127
|
+
<div className="text-[11px] text-current/70">{viewOption.description}</div>
|
|
128
|
+
</button>
|
|
129
|
+
))}
|
|
130
|
+
</div>
|
|
131
|
+
|
|
132
|
+
<div className="grid gap-4 lg:grid-cols-[minmax(0,2fr)_repeat(5,minmax(0,1fr))]">
|
|
133
|
+
<AdminFilterField label="Search" htmlFor="planned-message-search">
|
|
134
|
+
<input
|
|
135
|
+
id="planned-message-search"
|
|
136
|
+
type="text"
|
|
137
|
+
value={state.searchInput}
|
|
138
|
+
onChange={(event) => state.updateSearchInput(event.target.value)}
|
|
139
|
+
placeholder="Message / timeout id / agent / chat id / user"
|
|
140
|
+
className="w-full rounded-md border border-gray-300 px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
141
|
+
/>
|
|
142
|
+
</AdminFilterField>
|
|
143
|
+
|
|
144
|
+
<AdminFilterSelectField
|
|
145
|
+
id="planned-message-agent"
|
|
146
|
+
label="Agent"
|
|
147
|
+
value={state.filters.agentPermanentId}
|
|
148
|
+
onChange={state.updateAgentPermanentId}
|
|
149
|
+
options={agentSelectOptions}
|
|
150
|
+
/>
|
|
151
|
+
|
|
152
|
+
<AdminFilterSelectField
|
|
153
|
+
id="planned-message-recurrence"
|
|
154
|
+
label="Frequency"
|
|
155
|
+
value={state.filters.recurrence}
|
|
156
|
+
onChange={state.updateRecurrence}
|
|
157
|
+
options={PLANNED_MESSAGE_RECURRENCE_OPTIONS}
|
|
158
|
+
/>
|
|
159
|
+
|
|
160
|
+
<AdminFilterSelectField
|
|
161
|
+
id="planned-message-last-run"
|
|
162
|
+
label="Last run"
|
|
163
|
+
value={state.filters.lastRun}
|
|
164
|
+
onChange={state.updateLastRun}
|
|
165
|
+
options={PLANNED_MESSAGE_LAST_RUN_OPTIONS}
|
|
166
|
+
/>
|
|
167
|
+
|
|
168
|
+
<AdminFilterSelectField
|
|
169
|
+
id="planned-message-page-size"
|
|
170
|
+
label="Page size"
|
|
171
|
+
value={String(state.pageSize)}
|
|
172
|
+
onChange={state.updatePageSize}
|
|
173
|
+
options={PLANNED_MESSAGE_PAGE_SIZE_OPTIONS}
|
|
174
|
+
/>
|
|
175
|
+
|
|
176
|
+
<AdminFilterSelectField
|
|
177
|
+
id="planned-message-poll-interval"
|
|
178
|
+
label="Auto-refresh"
|
|
179
|
+
value={String(state.data.pollIntervalMs)}
|
|
180
|
+
onChange={state.data.updatePollIntervalMs}
|
|
181
|
+
options={PLANNED_MESSAGE_POLL_INTERVAL_OPTIONS}
|
|
182
|
+
/>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<div className="flex flex-wrap items-center justify-between gap-2 text-xs text-gray-500">
|
|
186
|
+
<span>{lastRefreshedLabel}</span>
|
|
187
|
+
<span>
|
|
188
|
+
A planned message is listed until it is cancelled or its plan is over, so a finished plan stays
|
|
189
|
+
readable here.
|
|
190
|
+
</span>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
</Card>
|
|
194
|
+
);
|
|
195
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
4
|
+
import { buildAgentProfileHref, buildExistingAgentChatHref } from '@/src/utils/agentRouting/agentRouteHrefs';
|
|
5
|
+
import { isPlannedMessageStillPlanned } from '@/src/utils/plannedMessageManager/isPlannedMessageStillPlanned';
|
|
6
|
+
import type { PlannedMessageManagerRecord } from '@/src/utils/plannedMessagesAdmin';
|
|
7
|
+
import { ArrowUpRight, MessageSquareText } from 'lucide-react';
|
|
8
|
+
import Link from 'next/link';
|
|
9
|
+
import type { PlannedMessageActionKind } from './usePlannedMessageManagerState';
|
|
10
|
+
import {
|
|
11
|
+
describePlannedMessagePlan,
|
|
12
|
+
formatPlannedMessageDateTime,
|
|
13
|
+
formatPlannedMessageEndReason,
|
|
14
|
+
formatPlannedMessageFrequency,
|
|
15
|
+
formatPlannedMessageRunCount,
|
|
16
|
+
PlannedMessageGoalChatBadge,
|
|
17
|
+
PlannedMessageLifecycleBadge,
|
|
18
|
+
resolvePlannedMessageText,
|
|
19
|
+
} from './plannedMessageManagerPresentation';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Props for one planned-message table row.
|
|
23
|
+
*
|
|
24
|
+
* @private function of PlannedMessageManagerTableCard
|
|
25
|
+
*/
|
|
26
|
+
type PlannedMessageManagerRowProps = {
|
|
27
|
+
readonly plannedMessage: PlannedMessageManagerRecord;
|
|
28
|
+
readonly language: ServerLanguageCode;
|
|
29
|
+
readonly busyTimeoutId: string | null;
|
|
30
|
+
readonly busyAction: PlannedMessageActionKind | null;
|
|
31
|
+
readonly onEdit: (plannedMessage: PlannedMessageManagerRecord) => void;
|
|
32
|
+
readonly onTogglePaused: (plannedMessage: PlannedMessageManagerRecord) => Promise<void>;
|
|
33
|
+
readonly onCancel: (plannedMessage: PlannedMessageManagerRecord) => Promise<void>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Shared classes of the small row action buttons.
|
|
38
|
+
*
|
|
39
|
+
* @private function of PlannedMessageManagerRow
|
|
40
|
+
*/
|
|
41
|
+
const PLANNED_MESSAGE_ACTION_BUTTON_CLASS_NAME =
|
|
42
|
+
'rounded-md border px-2.5 py-1 text-[11px] font-semibold disabled:cursor-not-allowed disabled:opacity-50';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Renders one planned message with its plan, its state, and what can be done to it.
|
|
46
|
+
*
|
|
47
|
+
* @private function of PlannedMessageManagerTableCard
|
|
48
|
+
*/
|
|
49
|
+
export function PlannedMessageManagerRow({
|
|
50
|
+
plannedMessage,
|
|
51
|
+
language,
|
|
52
|
+
busyTimeoutId,
|
|
53
|
+
busyAction,
|
|
54
|
+
onEdit,
|
|
55
|
+
onTogglePaused,
|
|
56
|
+
onCancel,
|
|
57
|
+
}: PlannedMessageManagerRowProps) {
|
|
58
|
+
const isStillPlanned = isPlannedMessageStillPlanned(plannedMessage.lifecycle);
|
|
59
|
+
const isFiringNow = plannedMessage.lifecycle === 'ONGOING';
|
|
60
|
+
const isBusy = busyTimeoutId === plannedMessage.timeoutId;
|
|
61
|
+
const isPaused = plannedMessage.pausedAt !== null;
|
|
62
|
+
const endReasonLabel = formatPlannedMessageEndReason(plannedMessage.endReason);
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Says whether one action of this very row is running right now.
|
|
66
|
+
*/
|
|
67
|
+
function isRunningAction(action: PlannedMessageActionKind): boolean {
|
|
68
|
+
return isBusy && busyAction === action;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<tr className="align-top">
|
|
73
|
+
<td className="px-4 py-3">
|
|
74
|
+
<div className="max-w-md text-[12px] font-medium text-gray-900">
|
|
75
|
+
{resolvePlannedMessageText(plannedMessage)}
|
|
76
|
+
</div>
|
|
77
|
+
<div className="mt-1 flex flex-wrap items-center gap-2">
|
|
78
|
+
<span className="break-all font-mono text-[11px] text-gray-500">{plannedMessage.timeoutId}</span>
|
|
79
|
+
<PlannedMessageGoalChatBadge plannedMessage={plannedMessage} />
|
|
80
|
+
</div>
|
|
81
|
+
</td>
|
|
82
|
+
|
|
83
|
+
<td className="px-4 py-3">
|
|
84
|
+
<div className="text-[12px] font-medium text-gray-900">
|
|
85
|
+
{plannedMessage.agentName || plannedMessage.agentPermanentId}
|
|
86
|
+
</div>
|
|
87
|
+
<div className="break-all text-[11px] text-gray-500">{plannedMessage.agentPermanentId}</div>
|
|
88
|
+
<div className="mt-1 text-[11px] text-gray-500">
|
|
89
|
+
{plannedMessage.username || `#${plannedMessage.userId}`}
|
|
90
|
+
</div>
|
|
91
|
+
<div className="mt-2 flex flex-wrap gap-2">
|
|
92
|
+
<Link
|
|
93
|
+
href={buildAgentProfileHref(plannedMessage.agentPermanentId)}
|
|
94
|
+
className="inline-flex items-center gap-1 rounded-md border border-blue-200 bg-blue-50 px-2.5 py-1 text-[11px] font-semibold text-blue-700 hover:bg-blue-100"
|
|
95
|
+
title="Open the agent this planned message belongs to"
|
|
96
|
+
>
|
|
97
|
+
<ArrowUpRight className="h-3.5 w-3.5" />
|
|
98
|
+
Open agent
|
|
99
|
+
</Link>
|
|
100
|
+
<Link
|
|
101
|
+
href={buildExistingAgentChatHref(plannedMessage.agentPermanentId, plannedMessage.chatId)}
|
|
102
|
+
className="inline-flex items-center gap-1 rounded-md border border-gray-200 bg-white px-2.5 py-1 text-[11px] font-semibold text-gray-700 hover:bg-gray-50"
|
|
103
|
+
title="Open the chat this planned message wakes up"
|
|
104
|
+
>
|
|
105
|
+
<MessageSquareText className="h-3.5 w-3.5" />
|
|
106
|
+
Open chat
|
|
107
|
+
</Link>
|
|
108
|
+
</div>
|
|
109
|
+
</td>
|
|
110
|
+
|
|
111
|
+
<td className="px-4 py-3">
|
|
112
|
+
<div className="text-[12px] text-gray-900">{formatPlannedMessageFrequency(plannedMessage)}</div>
|
|
113
|
+
<div className="mt-1 max-w-xs text-[11px] text-gray-500">
|
|
114
|
+
{describePlannedMessagePlan(plannedMessage)}
|
|
115
|
+
</div>
|
|
116
|
+
</td>
|
|
117
|
+
|
|
118
|
+
<td className="px-4 py-3 text-[11px] text-gray-800">
|
|
119
|
+
{isStillPlanned ? formatPlannedMessageDateTime(plannedMessage.dueAt, language) : '-'}
|
|
120
|
+
{plannedMessage.startsAt !== null && (
|
|
121
|
+
<div className="text-[11px] text-gray-500">
|
|
122
|
+
from {formatPlannedMessageDateTime(plannedMessage.startsAt, language)}
|
|
123
|
+
</div>
|
|
124
|
+
)}
|
|
125
|
+
{plannedMessage.endsAt !== null && (
|
|
126
|
+
<div className="text-[11px] text-gray-500">
|
|
127
|
+
until {formatPlannedMessageDateTime(plannedMessage.endsAt, language)}
|
|
128
|
+
</div>
|
|
129
|
+
)}
|
|
130
|
+
</td>
|
|
131
|
+
|
|
132
|
+
<td className="px-4 py-3 text-[11px] text-gray-800">
|
|
133
|
+
{formatPlannedMessageDateTime(plannedMessage.lastFiredAt, language)}
|
|
134
|
+
</td>
|
|
135
|
+
|
|
136
|
+
<td className="px-4 py-3 text-[11px] text-gray-800">{formatPlannedMessageRunCount(plannedMessage)}</td>
|
|
137
|
+
|
|
138
|
+
<td className="px-4 py-3">
|
|
139
|
+
<PlannedMessageLifecycleBadge lifecycle={plannedMessage.lifecycle} />
|
|
140
|
+
{endReasonLabel !== null && <div className="mt-1 text-[11px] text-gray-500">{endReasonLabel}</div>}
|
|
141
|
+
{plannedMessage.failureReason !== null && (
|
|
142
|
+
<div className="mt-1 max-w-xs break-words text-[11px] text-rose-700">
|
|
143
|
+
{plannedMessage.failureReason}
|
|
144
|
+
</div>
|
|
145
|
+
)}
|
|
146
|
+
</td>
|
|
147
|
+
|
|
148
|
+
<td className="px-4 py-3">
|
|
149
|
+
<div className="flex flex-wrap justify-end gap-2">
|
|
150
|
+
<button
|
|
151
|
+
type="button"
|
|
152
|
+
onClick={() => onEdit(plannedMessage)}
|
|
153
|
+
disabled={!isStillPlanned || isFiringNow || isBusy}
|
|
154
|
+
className={`${PLANNED_MESSAGE_ACTION_BUTTON_CLASS_NAME} border-gray-300 bg-white text-gray-700 hover:bg-gray-50`}
|
|
155
|
+
title={
|
|
156
|
+
isFiringNow
|
|
157
|
+
? 'This planned message is waking its agent right now, so its plan cannot be changed'
|
|
158
|
+
: 'Change the plan or the text of this planned message'
|
|
159
|
+
}
|
|
160
|
+
>
|
|
161
|
+
Edit
|
|
162
|
+
</button>
|
|
163
|
+
<button
|
|
164
|
+
type="button"
|
|
165
|
+
onClick={() => void onTogglePaused(plannedMessage)}
|
|
166
|
+
disabled={!isStillPlanned || isFiringNow || isBusy}
|
|
167
|
+
className={`${PLANNED_MESSAGE_ACTION_BUTTON_CLASS_NAME} border-orange-200 bg-orange-50 text-orange-700 hover:bg-orange-100`}
|
|
168
|
+
title={
|
|
169
|
+
isPaused
|
|
170
|
+
? 'Let this planned message wake its agent again'
|
|
171
|
+
: 'Hold this planned message back without cancelling it'
|
|
172
|
+
}
|
|
173
|
+
>
|
|
174
|
+
{isRunningAction('pause') ? 'Working…' : isPaused ? 'Resume' : 'Pause'}
|
|
175
|
+
</button>
|
|
176
|
+
<button
|
|
177
|
+
type="button"
|
|
178
|
+
onClick={() => void onCancel(plannedMessage)}
|
|
179
|
+
disabled={!isStillPlanned || isBusy}
|
|
180
|
+
className={`${PLANNED_MESSAGE_ACTION_BUTTON_CLASS_NAME} border-red-200 bg-red-50 text-red-700 hover:bg-red-100`}
|
|
181
|
+
title="Cancel this planned message so it never wakes its agent again"
|
|
182
|
+
>
|
|
183
|
+
{isRunningAction('cancel') ? 'Cancelling…' : 'Cancel'}
|
|
184
|
+
</button>
|
|
185
|
+
</div>
|
|
186
|
+
</td>
|
|
187
|
+
</tr>
|
|
188
|
+
);
|
|
189
|
+
}
|
package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerSummaryMetrics.tsx
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
4
|
+
import type { PlannedMessageManagerCounters } from '@/src/utils/plannedMessageManager/createPlannedMessageManagerCounters';
|
|
5
|
+
import { AdminMetricCard } from '../_components/AdminMetricCard';
|
|
6
|
+
import { formatPlannedMessageDateTime } from './plannedMessageManagerPresentation';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Props for the planned-message summary metrics grid.
|
|
10
|
+
*
|
|
11
|
+
* @private function of PlannedMessageManagerClient
|
|
12
|
+
*/
|
|
13
|
+
type PlannedMessageManagerSummaryMetricsProps = {
|
|
14
|
+
readonly counters: PlannedMessageManagerCounters;
|
|
15
|
+
readonly isLoading: boolean;
|
|
16
|
+
readonly language: ServerLanguageCode;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Renders the summary counters above the planned-message table.
|
|
21
|
+
*
|
|
22
|
+
* @private function of PlannedMessageManagerClient
|
|
23
|
+
*/
|
|
24
|
+
export function PlannedMessageManagerSummaryMetrics({
|
|
25
|
+
counters,
|
|
26
|
+
isLoading,
|
|
27
|
+
language,
|
|
28
|
+
}: PlannedMessageManagerSummaryMetricsProps) {
|
|
29
|
+
/**
|
|
30
|
+
* Formats one counter, keeping the loading placeholder until the first listing arrives.
|
|
31
|
+
*/
|
|
32
|
+
function formatCounter(count: number): string {
|
|
33
|
+
return isLoading ? '...' : count.toLocaleString();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
|
38
|
+
<AdminMetricCard
|
|
39
|
+
label="Ongoing"
|
|
40
|
+
value={formatCounter(counters.countByLifecycle.ONGOING)}
|
|
41
|
+
caption="Waking their agent right now"
|
|
42
|
+
/>
|
|
43
|
+
<AdminMetricCard
|
|
44
|
+
label="Scheduled"
|
|
45
|
+
value={formatCounter(counters.countByLifecycle.SCHEDULED + counters.countByLifecycle.NOT_STARTED)}
|
|
46
|
+
caption="Wake-ups still ahead"
|
|
47
|
+
/>
|
|
48
|
+
<AdminMetricCard
|
|
49
|
+
label="Paused"
|
|
50
|
+
value={formatCounter(counters.countByLifecycle.PAUSED)}
|
|
51
|
+
caption="Held back until resumed"
|
|
52
|
+
/>
|
|
53
|
+
<AdminMetricCard
|
|
54
|
+
label="Next wake-up"
|
|
55
|
+
value={isLoading ? '...' : formatPlannedMessageDateTime(counters.nextDueAt, language)}
|
|
56
|
+
caption="Earliest planned wake-up"
|
|
57
|
+
/>
|
|
58
|
+
</div>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import type { ServerLanguageCode } from '@/src/languages/ServerLanguageRegistry';
|
|
4
|
+
import type { PlannedMessageManagerSortField } from '@/src/utils/plannedMessagesAdmin';
|
|
5
|
+
import { Card } from '../../../components/Homepage/Card';
|
|
6
|
+
import { AdminSortableTableHeaderCell } from '../_components/AdminSortableTableHeaderCell';
|
|
7
|
+
import { PlannedMessageManagerRow } from './PlannedMessageManagerRow';
|
|
8
|
+
import type { UsePlannedMessageManagerStateResult } from './usePlannedMessageManagerState';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Sortable columns of the planned-message table, with the label used in their sort tooltip.
|
|
12
|
+
*
|
|
13
|
+
* @private function of PlannedMessageManagerTableCard
|
|
14
|
+
*/
|
|
15
|
+
const PLANNED_MESSAGE_SORT_COLUMNS: ReadonlyArray<{
|
|
16
|
+
readonly sortBy: PlannedMessageManagerSortField;
|
|
17
|
+
readonly heading: string;
|
|
18
|
+
readonly label: string;
|
|
19
|
+
}> = [
|
|
20
|
+
{ sortBy: 'plannedMessage', heading: 'Planned message', label: 'planned message' },
|
|
21
|
+
{ sortBy: 'agent', heading: 'Agent', label: 'agent' },
|
|
22
|
+
{ sortBy: 'frequency', heading: 'Frequency', label: 'frequency' },
|
|
23
|
+
{ sortBy: 'nextRun', heading: 'Next run', label: 'next run' },
|
|
24
|
+
{ sortBy: 'lastRun', heading: 'Last run', label: 'last run' },
|
|
25
|
+
{ sortBy: 'runs', heading: 'Runs', label: 'runs' },
|
|
26
|
+
{ sortBy: 'state', heading: 'State', label: 'state' },
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Props for the planned-message table card.
|
|
31
|
+
*
|
|
32
|
+
* @private function of PlannedMessageManagerClient
|
|
33
|
+
*/
|
|
34
|
+
type PlannedMessageManagerTableCardProps = {
|
|
35
|
+
readonly language: ServerLanguageCode;
|
|
36
|
+
readonly state: UsePlannedMessageManagerStateResult;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Renders the planned-message table with its loading, empty, and paging states.
|
|
41
|
+
*
|
|
42
|
+
* @private function of PlannedMessageManagerClient
|
|
43
|
+
*/
|
|
44
|
+
export function PlannedMessageManagerTableCard({ language, state }: PlannedMessageManagerTableCardProps) {
|
|
45
|
+
const firstVisibleIndex = Math.min((state.page - 1) * state.pageSize + 1, state.matchedCount);
|
|
46
|
+
const lastVisibleIndex = Math.min(state.page * state.pageSize, state.matchedCount);
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<Card className="hover:border-gray-200 hover:shadow-md">
|
|
50
|
+
<div className="flex items-center justify-between gap-4">
|
|
51
|
+
<div>
|
|
52
|
+
<h2 className="text-lg font-medium text-gray-900">
|
|
53
|
+
Planned messages ({state.matchedCount.toLocaleString()})
|
|
54
|
+
</h2>
|
|
55
|
+
<p className="mt-1 text-sm text-gray-500">
|
|
56
|
+
Every wake-up an agent planned for itself or for one of its chats.
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
{state.data.isRefreshing ? (
|
|
60
|
+
<span className="text-xs font-medium text-blue-600">Refreshing…</span>
|
|
61
|
+
) : null}
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
{state.data.isLoading ? (
|
|
65
|
+
<div className="py-10 text-center text-sm text-gray-500">Loading planned messages…</div>
|
|
66
|
+
) : state.visiblePlannedMessages.length === 0 ? (
|
|
67
|
+
<div className="py-10 text-center text-sm text-gray-500">
|
|
68
|
+
No planned message matches the selected filters.
|
|
69
|
+
</div>
|
|
70
|
+
) : (
|
|
71
|
+
<div className="mt-4 overflow-x-auto">
|
|
72
|
+
<table className="min-w-full divide-y divide-gray-200 text-xs">
|
|
73
|
+
<thead className="bg-gray-50 text-gray-500">
|
|
74
|
+
<tr>
|
|
75
|
+
{PLANNED_MESSAGE_SORT_COLUMNS.map((column) => (
|
|
76
|
+
<AdminSortableTableHeaderCell
|
|
77
|
+
key={column.sortBy}
|
|
78
|
+
className="px-4 py-3 text-left font-semibold"
|
|
79
|
+
label={column.label}
|
|
80
|
+
sortBy={column.sortBy}
|
|
81
|
+
activeSortBy={state.sortBy}
|
|
82
|
+
sortOrder={state.sortOrder}
|
|
83
|
+
onSortChange={state.handleSortChange}
|
|
84
|
+
>
|
|
85
|
+
{column.heading}
|
|
86
|
+
</AdminSortableTableHeaderCell>
|
|
87
|
+
))}
|
|
88
|
+
<th className="px-4 py-3 text-right font-semibold">Actions</th>
|
|
89
|
+
</tr>
|
|
90
|
+
</thead>
|
|
91
|
+
<tbody className="divide-y divide-gray-200 bg-white">
|
|
92
|
+
{state.visiblePlannedMessages.map((plannedMessage) => (
|
|
93
|
+
<PlannedMessageManagerRow
|
|
94
|
+
key={plannedMessage.timeoutId}
|
|
95
|
+
plannedMessage={plannedMessage}
|
|
96
|
+
language={language}
|
|
97
|
+
busyTimeoutId={state.busyTimeoutId}
|
|
98
|
+
busyAction={state.busyAction}
|
|
99
|
+
onEdit={state.openPlannedMessageEditor}
|
|
100
|
+
onTogglePaused={state.togglePlannedMessagePaused}
|
|
101
|
+
onCancel={state.cancelPlannedMessage}
|
|
102
|
+
/>
|
|
103
|
+
))}
|
|
104
|
+
</tbody>
|
|
105
|
+
</table>
|
|
106
|
+
</div>
|
|
107
|
+
)}
|
|
108
|
+
|
|
109
|
+
<div className="mt-4 flex flex-col items-center justify-between gap-3 border-t border-gray-100 pt-4 text-xs text-gray-600 md:flex-row">
|
|
110
|
+
<div>
|
|
111
|
+
{state.matchedCount > 0 ? (
|
|
112
|
+
<>
|
|
113
|
+
Showing <span className="font-semibold">{firstVisibleIndex}</span> –{' '}
|
|
114
|
+
<span className="font-semibold">{lastVisibleIndex}</span> of{' '}
|
|
115
|
+
<span className="font-semibold">{state.matchedCount}</span> planned messages
|
|
116
|
+
</>
|
|
117
|
+
) : (
|
|
118
|
+
'No planned messages'
|
|
119
|
+
)}
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<div className="flex items-center gap-2">
|
|
123
|
+
<button
|
|
124
|
+
type="button"
|
|
125
|
+
onClick={state.goToPreviousPage}
|
|
126
|
+
disabled={state.isPreviousPageDisabled}
|
|
127
|
+
className="rounded-md border border-gray-300 px-3 py-1.5 font-medium text-gray-700 disabled:cursor-not-allowed disabled:opacity-50"
|
|
128
|
+
>
|
|
129
|
+
Previous
|
|
130
|
+
</button>
|
|
131
|
+
<span>
|
|
132
|
+
Page <span className="font-semibold">{state.page}</span> of{' '}
|
|
133
|
+
<span className="font-semibold">{state.totalPages}</span>
|
|
134
|
+
</span>
|
|
135
|
+
<button
|
|
136
|
+
type="button"
|
|
137
|
+
onClick={state.goToNextPage}
|
|
138
|
+
disabled={state.isNextPageDisabled}
|
|
139
|
+
className="rounded-md border border-gray-300 px-3 py-1.5 font-medium text-gray-700 disabled:cursor-not-allowed disabled:opacity-50"
|
|
140
|
+
>
|
|
141
|
+
Next
|
|
142
|
+
</button>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</Card>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ForbiddenPage } from '../../../components/ForbiddenPage/ForbiddenPage';
|
|
2
|
+
import { isUserAdmin } from '../../../utils/isUserAdmin';
|
|
3
|
+
import { isUserGlobalAdmin } from '../../../utils/isUserGlobalAdmin';
|
|
4
|
+
import { PlannedMessageManagerClient } from './PlannedMessageManagerClient';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Admin page managing every planned message (durable chat timeout) of the server.
|
|
8
|
+
*/
|
|
9
|
+
export default async function AdminPlannedMessagesPage() {
|
|
10
|
+
const [isAdmin, isSuperAdmin] = await Promise.all([isUserAdmin(), isUserGlobalAdmin()]);
|
|
11
|
+
|
|
12
|
+
if (!isAdmin) {
|
|
13
|
+
return <ForbiddenPage />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return <PlannedMessageManagerClient isSuperAdmin={isSuperAdmin} />;
|
|
17
|
+
}
|