@promptbook/cli 0.114.0-13 → 0.114.0-18

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.
Files changed (231) hide show
  1. package/apps/agents-server/next.config.ts +6 -0
  2. package/apps/agents-server/src/app/admin/_components/AdminFilterFields.tsx +84 -0
  3. package/apps/agents-server/src/app/admin/_components/AdminMetricCard.tsx +36 -0
  4. package/apps/agents-server/src/app/admin/_components/AdminTaskManagerTabs.tsx +97 -0
  5. package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerClient.tsx +103 -0
  6. package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerEditDialog.tsx +232 -0
  7. package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerFiltersCard.tsx +195 -0
  8. package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerRow.tsx +189 -0
  9. package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerSummaryMetrics.tsx +60 -0
  10. package/apps/agents-server/src/app/admin/planned-messages/PlannedMessageManagerTableCard.tsx +147 -0
  11. package/apps/agents-server/src/app/admin/planned-messages/page.tsx +17 -0
  12. package/apps/agents-server/src/app/admin/planned-messages/plannedMessageEditForm.ts +186 -0
  13. package/apps/agents-server/src/app/admin/planned-messages/plannedMessageManagerDialogs.ts +46 -0
  14. package/apps/agents-server/src/app/admin/planned-messages/plannedMessageManagerPresentation.tsx +188 -0
  15. package/apps/agents-server/src/app/admin/planned-messages/resolvePlannedMessageSortValue.ts +115 -0
  16. package/apps/agents-server/src/app/admin/planned-messages/usePlannedMessageManagerData.ts +116 -0
  17. package/apps/agents-server/src/app/admin/planned-messages/usePlannedMessageManagerState.ts +289 -0
  18. package/apps/agents-server/src/app/admin/task-manager/TaskManagerClient.tsx +7 -2
  19. package/apps/agents-server/src/app/admin/task-manager/TaskManagerFiltersCard.tsx +7 -73
  20. package/apps/agents-server/src/app/admin/task-manager/TaskManagerSummaryMetrics.tsx +5 -30
  21. package/apps/agents-server/src/app/admin/task-manager/[taskId]/TaskManagerTaskDetailClient.tsx +1 -1
  22. package/apps/agents-server/src/app/agents/[agentName]/api/book/reference-diagnostics/route.ts +30 -7
  23. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +1 -0
  24. package/apps/agents-server/src/app/agents/[agentName]/api/book/test.http +3 -3
  25. package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorMissingReferences.tsx +106 -12
  26. package/apps/agents-server/src/app/agents/[agentName]/book/BookEditorWrapper.tsx +3 -0
  27. package/apps/agents-server/src/app/agents/[agentName]/book/useBookEditorDiagnostics.ts +12 -0
  28. package/apps/agents-server/src/app/agents/[agentName]/book/useBookEditorWrapper.tsx +2 -0
  29. package/apps/agents-server/src/app/agents/[agentName]/chat/AgentGoalChatPlannedMessages.tsx +46 -3
  30. package/apps/agents-server/src/app/api/admin/default-agents/reinstate/route.ts +5 -1
  31. package/apps/agents-server/src/app/api/admin/planned-messages/[timeoutId]/route.ts +80 -0
  32. package/apps/agents-server/src/app/api/admin/planned-messages/route.ts +19 -0
  33. package/apps/agents-server/src/app/api/internal/agent-goal-chat-planned-messages/route.ts +30 -2
  34. package/apps/agents-server/src/components/DefaultAgents/ReinstateBundledAgentsButton.tsx +7 -0
  35. package/apps/agents-server/src/components/DefaultAgents/coreAgentsAdminRoute.ts +6 -0
  36. package/apps/agents-server/src/components/Header/buildHeaderSystemMenuItems.ts +7 -0
  37. package/apps/agents-server/src/components/Homepage/DefaultAgentsStatusNotice.tsx +1 -7
  38. package/apps/agents-server/src/database/migrations/2026-08-1800-user-chat-timeout-schedule.sql +11 -0
  39. package/apps/agents-server/src/instrumentation-node.ts +18 -0
  40. package/apps/agents-server/src/languages/ServerTranslationKeys.ts +4 -0
  41. package/apps/agents-server/src/languages/translations/czech.yaml +4 -0
  42. package/apps/agents-server/src/languages/translations/english.yaml +4 -0
  43. package/apps/agents-server/src/tools/agentGoalChatTimeoutToolFunctions.ts +62 -15
  44. package/apps/agents-server/src/tools/agentGoalChatTimeoutTools.ts +63 -9
  45. package/apps/agents-server/src/utils/adminEntityLookups/loadAgentNamesByPermanentId.ts +45 -0
  46. package/apps/agents-server/src/utils/adminEntityLookups/loadUsernamesByUserId.ts +36 -0
  47. package/apps/agents-server/src/utils/adminEntityLookups.ts +2 -0
  48. package/apps/agents-server/src/utils/agentGoalChat/agentGoalChatPlannedMessageActions.ts +299 -52
  49. package/apps/agents-server/src/utils/agentGoalChat/createAgentGoalChatNoteContent.ts +45 -17
  50. package/apps/agents-server/src/utils/agentGoalChat.ts +1 -0
  51. package/apps/agents-server/src/utils/agentProjects/agentProjectIdentity.ts +46 -0
  52. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeAutostartScheduler.ts +162 -0
  53. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeDesiredState.ts +252 -0
  54. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeDisplay.ts +6 -3
  55. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeDomains.ts +2 -44
  56. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimePaths.ts +25 -0
  57. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimePm2.ts +4 -3
  58. package/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeRegistry.ts +77 -24
  59. package/apps/agents-server/src/utils/agentProjects/agentProjectStateMutationQueue.ts +58 -0
  60. package/apps/agents-server/src/utils/agentProjects/listAllLocalAgentProjectIdentities.ts +48 -0
  61. package/apps/agents-server/src/utils/agentProjects/resolveAgentProjectRuntimeEnvironmentFlag.ts +23 -0
  62. package/apps/agents-server/src/utils/agentProjects/resolveAgentProjectRuntimeStatus.ts +73 -0
  63. package/apps/agents-server/src/utils/agentProjects/startDefaultAgentProjectRuntimes.ts +110 -0
  64. package/apps/agents-server/src/utils/agentReferenceResolver/MissingCoreAgentRecovery.ts +19 -0
  65. package/apps/agents-server/src/utils/agentReferenceResolver/bookScopedAgentReferences.ts +7 -0
  66. package/apps/agents-server/src/utils/agentReferenceResolver/createAgentInheritanceDiagnostics.ts +457 -0
  67. package/apps/agents-server/src/utils/agentReferenceResolver/createUnresolvedAgentReferenceDiagnostics.ts +27 -0
  68. package/apps/agents-server/src/utils/agentReferenceResolver/resolveCoreAgentAwareMissingReferences.ts +156 -0
  69. package/apps/agents-server/src/utils/chatMessageChips/createAnsweredMessageChipToolCalls.ts +15 -3
  70. package/apps/agents-server/src/utils/chatMessageChips/createPlannedMessageChipToolCalls.ts +8 -3
  71. package/apps/agents-server/src/utils/chatMessageChips/createTouchedExternalSourceChipToolCalls.ts +39 -0
  72. package/apps/agents-server/src/utils/chatMessageChips/createTouchedProjectChipResult.ts +45 -0
  73. package/apps/agents-server/src/utils/chatMessageChips/createTouchedProjectChipToolCalls.ts +58 -24
  74. package/apps/agents-server/src/utils/cronExpression/CronExpression.ts +63 -0
  75. package/apps/agents-server/src/utils/cronExpression/normalizeCronExpression.ts +34 -0
  76. package/apps/agents-server/src/utils/cronExpression/normalizeCronExpressionWhitespace.ts +11 -0
  77. package/apps/agents-server/src/utils/cronExpression/parseCronExpression.ts +41 -0
  78. package/apps/agents-server/src/utils/cronExpression/parseCronExpressionField.ts +140 -0
  79. package/apps/agents-server/src/utils/cronExpression/resolveNextCronRun.ts +100 -0
  80. package/apps/agents-server/src/utils/cronExpression/throwInvalidCronExpressionField.ts +20 -0
  81. package/apps/agents-server/src/utils/cronExpression.ts +10 -0
  82. package/apps/agents-server/src/utils/explicitFromCommitment.ts +130 -0
  83. package/apps/agents-server/src/utils/getAdminChatTasksResponse/getAdminChatTasks/loadAdminChatTaskFallbackData.ts +3 -77
  84. package/apps/agents-server/src/utils/localChatRunner/applyLocalAgentPlannedMessageCommands.ts +53 -4
  85. package/apps/agents-server/src/utils/localChatRunner/prepareLocalAgentPlannedMessagesSidecar.ts +15 -7
  86. package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +8 -0
  87. package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentBooks.ts +5 -11
  88. package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentRuntime.ts +2 -2
  89. package/apps/agents-server/src/utils/managementApi/managementApiSchemas.ts +2 -2
  90. package/apps/agents-server/src/utils/plannedMessageManager/cancelManagedPlannedMessage.ts +35 -0
  91. package/apps/agents-server/src/utils/plannedMessageManager/collectPlannedMessageAgentOptions.ts +56 -0
  92. package/apps/agents-server/src/utils/plannedMessageManager/createPlannedMessageManagerCounters.ts +104 -0
  93. package/apps/agents-server/src/utils/plannedMessageManager/filterPlannedMessages.ts +191 -0
  94. package/apps/agents-server/src/utils/plannedMessageManager/getPlannedMessageManagerResponse.ts +55 -0
  95. package/apps/agents-server/src/utils/plannedMessageManager/isPlannedMessageStillPlanned.ts +18 -0
  96. package/apps/agents-server/src/utils/plannedMessageManager/loadPlannedMessageManagerRecord.ts +32 -0
  97. package/apps/agents-server/src/utils/plannedMessageManager/mapPlannedMessageManagerRecord.ts +73 -0
  98. package/apps/agents-server/src/utils/plannedMessageManager/parsePlannedMessageManagerUpdateRequest.ts +76 -0
  99. package/apps/agents-server/src/utils/plannedMessageManager/resolvePlannedMessageEndReason.ts +59 -0
  100. package/apps/agents-server/src/utils/plannedMessageManager/resolvePlannedMessageLifecycle.ts +99 -0
  101. package/apps/agents-server/src/utils/plannedMessageManager/resolvePlannedMessageRecurrenceKind.ts +40 -0
  102. package/apps/agents-server/src/utils/plannedMessageManager/updateManagedPlannedMessage.ts +121 -0
  103. package/apps/agents-server/src/utils/plannedMessagesAdmin.ts +200 -0
  104. package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +114 -95
  105. package/apps/agents-server/src/utils/userChatClient.ts +4 -0
  106. package/apps/agents-server/src/utils/userChatTimeout/UserChatTimeoutRecord.ts +37 -1
  107. package/apps/agents-server/src/utils/userChatTimeout/agentScopedTimeoutBulkActions.ts +11 -17
  108. package/apps/agents-server/src/utils/userChatTimeout/createTimeoutWakeUpMessage.ts +37 -13
  109. package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/PlannedMessageSchedule.ts +52 -0
  110. package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/hasPlannedMessageRecurrence.ts +13 -0
  111. package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/isPlannedMessageScheduleFinished.ts +30 -0
  112. package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/normalizePlannedMessageScheduleValues.ts +62 -0
  113. package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/parsePlannedMessageSchedule.ts +202 -0
  114. package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule/resolvePlannedMessageDueAt.ts +121 -0
  115. package/apps/agents-server/src/utils/userChatTimeout/plannedMessageSchedule.ts +12 -0
  116. package/apps/agents-server/src/utils/userChatTimeout/setAgentScopedUserChatTimeoutPausedState.ts +66 -0
  117. package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/createUserChatTimeout.ts +76 -5
  118. package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/listAllUserChatTimeouts.ts +37 -0
  119. package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/mapUserChatTimeoutRow.ts +9 -0
  120. package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/repeatFiredUserChatTimeout.ts +19 -9
  121. package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore/updateAgentScopedUserChatTimeout.ts +39 -6
  122. package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutStore.ts +1 -0
  123. package/apps/agents-server/src/utils/userChatTimeout/userChatTimeoutWorker.ts +110 -11
  124. package/apps/agents-server/src/utils/userChatTimeout.ts +16 -0
  125. package/apps/agents-server/src/utils/vpsSelfUpdate/vpsSelfUpdateCron.ts +23 -316
  126. package/apps/agents-server/tests/e2e/support/AgentManagementApi.ts +3 -3
  127. package/esm/index.es.js +951 -102
  128. package/esm/index.es.js.map +1 -1
  129. package/esm/scripts/run-agent-messages/git/commitAgentProjectChanges.d.ts +15 -0
  130. package/esm/scripts/run-agent-messages/git/commitAnsweredMessageProjectChanges.d.ts +24 -0
  131. package/esm/scripts/run-agent-messages/git/ensureAgentProjectGitRepository.d.ts +20 -0
  132. package/esm/scripts/run-agent-messages/git/readAgentProjectCommitChange.d.ts +11 -0
  133. package/esm/scripts/run-agent-messages/git/runAgentProjectGitCommand.d.ts +29 -0
  134. package/esm/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +3 -3
  135. package/esm/scripts/run-agent-messages/messages/listAgentProjectDirectoryNames.d.ts +7 -0
  136. package/esm/scripts/run-agent-messages/messages/resolveAnsweredMessageTouches.d.ts +29 -0
  137. package/esm/scripts/run-codex-prompts/ping/pingCoderHarnessPeriodically.d.ts +22 -0
  138. package/esm/src/book-3.0/AgentMessageRunReport.d.ts +18 -0
  139. package/esm/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +38 -5
  140. package/esm/src/book-3.0/describeAgentPlannedMessageSchedule.d.ts +31 -0
  141. package/esm/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +1 -9
  142. package/esm/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.d.ts +28 -0
  143. package/esm/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.test.d.ts +1 -0
  144. package/esm/src/book-components/Chat/Chat/renderAgentProjectDiff.d.ts +13 -0
  145. package/esm/src/book-components/Chat/Chat/renderAgentProjectToolCallDetails.d.ts +16 -0
  146. package/esm/src/book-components/Chat/utils/agentProjectToolCall.d.ts +39 -0
  147. package/esm/src/book-components/Chat/utils/agentProjectToolCall.test.d.ts +1 -0
  148. package/esm/src/book-components/Chat/utils/externalSourceToolCall.d.ts +38 -0
  149. package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +6 -0
  150. package/esm/src/cli/cli-commands/coder/waitOptions.d.ts +12 -0
  151. package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +15 -0
  152. package/esm/src/utils/agent-message-runtime/AgentMessageProjectChange.d.ts +76 -0
  153. package/esm/src/utils/agent-message-runtime/AgentMessageTouchedExternalSource.d.ts +45 -0
  154. package/esm/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +3 -0
  155. package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.d.ts +18 -0
  156. package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.test.d.ts +1 -0
  157. package/esm/src/utils/random/$generateBookBoilerplate.test.d.ts +1 -0
  158. package/esm/src/version.d.ts +1 -1
  159. package/package.json +1 -1
  160. package/src/book-2.0/agent-source/string_book.ts +1 -1
  161. package/src/book-2.0/book-language-documentation/czechBookLanguageManualDictionary.ts +6 -1
  162. package/src/book-2.0/book-language-documentation/englishBookLanguageManualDictionary.ts +6 -1
  163. package/src/book-3.0/AgentMessageRunReport.ts +59 -0
  164. package/src/book-3.0/AgentPlannedMessagesSidecar.ts +64 -9
  165. package/src/book-3.0/describeAgentPlannedMessageSchedule.ts +94 -0
  166. package/src/book-components/BookEditor/BookEditorMonaco.tsx +2 -0
  167. package/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.ts +3 -11
  168. package/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.ts +71 -0
  169. package/src/book-components/Chat/Chat/Chat.module.css +165 -18
  170. package/src/book-components/Chat/Chat/ChatMessageMap.tsx +0 -1
  171. package/src/book-components/Chat/Chat/renderAgentProjectDiff.tsx +85 -0
  172. package/src/book-components/Chat/Chat/renderAgentProjectToolCallDetails.tsx +206 -0
  173. package/src/book-components/Chat/Chat/renderToolCallDetails.tsx +8 -0
  174. package/src/book-components/Chat/MarkdownContent/MarkdownContent.tsx +2 -3
  175. package/src/book-components/Chat/utils/agentProjectToolCall.ts +82 -5
  176. package/src/book-components/Chat/utils/externalSourceToolCall.ts +65 -0
  177. package/src/book-components/Chat/utils/getToolCallChipletInfo.ts +36 -0
  178. package/src/book-components/Chat/utils/renderMarkdown.ts +3 -10
  179. package/src/book-components/Chat/utils/timeoutToolCallPresentation.ts +12 -1
  180. package/src/cli/cli-commands/coder/ping.ts +35 -9
  181. package/src/cli/cli-commands/coder/waitOptions.ts +33 -0
  182. package/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.ts +3 -1
  183. package/src/cli/cli-commands/common/harness/$checkHarnessInstallation.ts +3 -1
  184. package/src/cli/cli-commands/common/harnessUpdateCliOptions.ts +1 -4
  185. package/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.ts +47 -3
  186. package/src/commands/FORMAT/formatCommandParser.ts +4 -2
  187. package/src/commitments/FROM/FROM.ts +13 -0
  188. package/src/other/templates/getTemplatesPipelineCollection.ts +819 -751
  189. package/src/utils/agent-message-runtime/AgentMessageProjectChange.ts +183 -0
  190. package/src/utils/agent-message-runtime/AgentMessageTouchedExternalSource.ts +80 -0
  191. package/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.ts +3 -0
  192. package/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.ts +2 -4
  193. package/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.ts +341 -0
  194. package/src/utils/random/$generateBookBoilerplate.ts +1 -1
  195. package/src/version.ts +2 -2
  196. package/src/versions.txt +5 -0
  197. package/umd/index.umd.js +950 -101
  198. package/umd/index.umd.js.map +1 -1
  199. package/umd/scripts/run-agent-messages/git/commitAgentProjectChanges.d.ts +15 -0
  200. package/umd/scripts/run-agent-messages/git/commitAnsweredMessageProjectChanges.d.ts +24 -0
  201. package/umd/scripts/run-agent-messages/git/ensureAgentProjectGitRepository.d.ts +20 -0
  202. package/umd/scripts/run-agent-messages/git/readAgentProjectCommitChange.d.ts +11 -0
  203. package/umd/scripts/run-agent-messages/git/runAgentProjectGitCommand.d.ts +29 -0
  204. package/umd/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +3 -3
  205. package/umd/scripts/run-agent-messages/messages/listAgentProjectDirectoryNames.d.ts +7 -0
  206. package/umd/scripts/run-agent-messages/messages/resolveAnsweredMessageTouches.d.ts +29 -0
  207. package/umd/scripts/run-codex-prompts/ping/pingCoderHarnessPeriodically.d.ts +22 -0
  208. package/umd/src/book-3.0/AgentMessageRunReport.d.ts +18 -0
  209. package/umd/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +38 -5
  210. package/umd/src/book-3.0/describeAgentPlannedMessageSchedule.d.ts +31 -0
  211. package/umd/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +1 -9
  212. package/umd/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.d.ts +28 -0
  213. package/umd/src/book-components/BookEditor/createDuplicateFromCommitmentDiagnostics.test.d.ts +1 -0
  214. package/umd/src/book-components/Chat/Chat/renderAgentProjectDiff.d.ts +13 -0
  215. package/umd/src/book-components/Chat/Chat/renderAgentProjectToolCallDetails.d.ts +16 -0
  216. package/umd/src/book-components/Chat/utils/agentProjectToolCall.d.ts +39 -0
  217. package/umd/src/book-components/Chat/utils/agentProjectToolCall.test.d.ts +1 -0
  218. package/umd/src/book-components/Chat/utils/externalSourceToolCall.d.ts +38 -0
  219. package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +6 -0
  220. package/umd/src/cli/cli-commands/coder/waitOptions.d.ts +12 -0
  221. package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +15 -0
  222. package/umd/src/utils/agent-message-runtime/AgentMessageProjectChange.d.ts +76 -0
  223. package/umd/src/utils/agent-message-runtime/AgentMessageTouchedExternalSource.d.ts +45 -0
  224. package/umd/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +3 -0
  225. package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.d.ts +18 -0
  226. package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedExternalSources.test.d.ts +1 -0
  227. package/umd/src/utils/random/$generateBookBoilerplate.test.d.ts +1 -0
  228. package/umd/src/version.d.ts +1 -1
  229. package/apps/agents-server/src/app/admin/task-manager/TaskManagerScopeTabs.tsx +0 -74
  230. package/esm/scripts/run-agent-messages/messages/resolveTouchedAgentProjects.d.ts +0 -15
  231. package/umd/scripts/run-agent-messages/messages/resolveTouchedAgentProjects.d.ts +0 -15
@@ -1,15 +1,20 @@
1
1
  import type { ToolCall } from '@promptbook-local/types';
2
+ import type { AgentMessageProjectChange } from '../../../../../src/utils/agent-message-runtime/AgentMessageProjectChange';
3
+ import type { AgentMessageTouchedExternalSource } from '../../../../../src/utils/agent-message-runtime/AgentMessageTouchedExternalSource';
2
4
  import type { AppliedAgentPlannedMessageCommand } from '../localChatRunner/applyLocalAgentPlannedMessageCommands';
3
5
  import { createPlannedMessageChipToolCalls } from './createPlannedMessageChipToolCalls';
6
+ import { createTouchedExternalSourceChipToolCalls } from './createTouchedExternalSourceChipToolCalls';
4
7
  import { createTouchedProjectChipToolCalls } from './createTouchedProjectChipToolCalls';
5
8
 
6
9
  /**
7
10
  * Creates every extra chip shown below one answered chat message.
8
11
  *
9
12
  * This is the single place deciding what an answer shows besides its text: the wake-ups it
10
- * planned and the projects it worked with. The chips travel as tool calls of the assistant
11
- * message, so they are visible in every chat view — including external chats such as email,
12
- * whose outbound reply is rendered from the message text alone and therefore stays unchanged.
13
+ * planned, the projects it worked with including what it changed in them — and the sources
14
+ * outside the agent it touched. The chips
15
+ * travel as tool calls of the assistant message, so they are visible in every chat view —
16
+ * including external chats such as email, whose outbound reply is rendered from the message text
17
+ * alone and therefore stays unchanged.
13
18
  *
14
19
  * @param options - Owning agent plus what the answered message planned and touched.
15
20
  * @returns Tool calls rendered as chips below the answer, in a stable order.
@@ -18,17 +23,24 @@ export async function createAnsweredMessageChipToolCalls(options: {
18
23
  readonly agentPermanentId: string;
19
24
  readonly appliedPlannedMessageCommands: ReadonlyArray<AppliedAgentPlannedMessageCommand>;
20
25
  readonly touchedProjectNames: ReadonlyArray<string>;
26
+ readonly projectChanges?: ReadonlyArray<AgentMessageProjectChange>;
27
+ readonly touchedExternalSources: ReadonlyArray<AgentMessageTouchedExternalSource>;
21
28
  readonly createdAt?: NonNullable<ToolCall['createdAt']>;
22
29
  }): Promise<ReadonlyArray<ToolCall>> {
23
30
  const createdAt = options.createdAt || (new Date().toISOString() as NonNullable<ToolCall['createdAt']>);
24
31
  const projectChipToolCalls = await createTouchedProjectChipToolCalls({
25
32
  agentPermanentId: options.agentPermanentId,
26
33
  touchedProjectNames: options.touchedProjectNames,
34
+ projectChanges: options.projectChanges || [],
27
35
  createdAt,
28
36
  });
29
37
 
30
38
  return [
31
39
  ...projectChipToolCalls,
40
+ ...createTouchedExternalSourceChipToolCalls({
41
+ touchedExternalSources: options.touchedExternalSources,
42
+ createdAt,
43
+ }),
32
44
  ...createPlannedMessageChipToolCalls({
33
45
  appliedCommands: options.appliedPlannedMessageCommands,
34
46
  createdAt,
@@ -11,11 +11,12 @@ import type { AppliedAgentPlannedMessageCommand } from '../localChatRunner/apply
11
11
  const PLANNED_MESSAGE_CHIP_IDEMPOTENCY_PREFIX = 'planned-message';
12
12
 
13
13
  /**
14
- * Creates the timeout chips of the message that planned or cancelled a wake-up.
14
+ * Creates the timeout chips of the message that planned, re-planned, or cancelled a wake-up.
15
15
  *
16
16
  * The chat already renders `set_timeout` and `cancel_timeout` tool calls as timeout chips with a
17
17
  * detail popup, so one planned message becomes exactly one such tool call instead of a second
18
- * timeout presentation.
18
+ * timeout presentation. A re-planned message keeps the scheduling chip, because it still ends with a
19
+ * wake-up waiting ahead.
19
20
  *
20
21
  * @param options - Planned-message commands applied for one answered message.
21
22
  * @returns Timeout tool calls shown as chips below the answer.
@@ -25,9 +26,13 @@ export function createPlannedMessageChipToolCalls(options: {
25
26
  readonly createdAt: NonNullable<ToolCall['createdAt']>;
26
27
  }): ReadonlyArray<ToolCall> {
27
28
  return options.appliedCommands.map(({ command, result }) => ({
28
- name: result.action === 'set' ? SET_TIMEOUT_TOOL_CALL_NAME : CANCEL_TIMEOUT_TOOL_CALL_NAME,
29
+ name: result.action === 'cancel' ? CANCEL_TIMEOUT_TOOL_CALL_NAME : SET_TIMEOUT_TOOL_CALL_NAME,
29
30
  arguments: {
30
31
  ...(command.milliseconds === undefined ? {} : { milliseconds: command.milliseconds }),
32
+ ...(command.cronExpression === undefined ? {} : { cronExpression: command.cronExpression }),
33
+ ...(command.startsAt === undefined ? {} : { startsAt: command.startsAt }),
34
+ ...(command.endsAt === undefined ? {} : { endsAt: command.endsAt }),
35
+ ...(command.maxRunCount === undefined ? {} : { maxRunCount: command.maxRunCount }),
31
36
  ...(command.message === undefined ? {} : { message: command.message }),
32
37
  ...(command.timeoutId === undefined ? {} : { timeoutId: command.timeoutId }),
33
38
  },
@@ -0,0 +1,39 @@
1
+ import type { ToolCall } from '@promptbook-local/types';
2
+ import { EXTERNAL_SOURCE_TOOL_CALL_NAME } from '../../../../../src/book-components/Chat/utils/externalSourceToolCall';
3
+ import type { AgentMessageTouchedExternalSource } from '../../../../../src/utils/agent-message-runtime/AgentMessageTouchedExternalSource';
4
+
5
+ /**
6
+ * Prefix of the idempotency keys identifying touched-external-source chips.
7
+ */
8
+ const TOUCHED_EXTERNAL_SOURCE_CHIP_IDEMPOTENCY_PREFIX = 'external-source';
9
+
10
+ /**
11
+ * Creates the external-source chips of one answered message.
12
+ *
13
+ * An external source is reported by the runner once the answering harness reached beyond the
14
+ * agent itself — an integration such as Gmail, a website, or a web search — so the chat always
15
+ * tells which outside services and addresses one answer really involved. Work the agent does
16
+ * only inside itself reaches this with an empty list and therefore shows no chip.
17
+ *
18
+ * @param options - External sources the answer touched.
19
+ * @returns External-source tool calls shown as chips below the answer.
20
+ */
21
+ export function createTouchedExternalSourceChipToolCalls(options: {
22
+ readonly touchedExternalSources: ReadonlyArray<AgentMessageTouchedExternalSource>;
23
+ readonly createdAt: NonNullable<ToolCall['createdAt']>;
24
+ }): ReadonlyArray<ToolCall> {
25
+ return options.touchedExternalSources.map((touchedExternalSource) => ({
26
+ name: EXTERNAL_SOURCE_TOOL_CALL_NAME,
27
+ arguments: {
28
+ kind: touchedExternalSource.kind,
29
+ name: touchedExternalSource.name,
30
+ ...(touchedExternalSource.url === undefined ? {} : { url: touchedExternalSource.url }),
31
+ },
32
+ result: touchedExternalSource,
33
+ state: 'COMPLETE',
34
+ idempotencyKey: `${TOUCHED_EXTERNAL_SOURCE_CHIP_IDEMPOTENCY_PREFIX}-${
35
+ touchedExternalSource.kind
36
+ }-${touchedExternalSource.name.toLowerCase()}`,
37
+ createdAt: options.createdAt,
38
+ }));
39
+ }
@@ -0,0 +1,45 @@
1
+ import type { AgentProjectToolCallResult } from '../../../../../src/book-components/Chat/utils/agentProjectToolCall';
2
+ import type { AgentMessageProjectChange } from '../../../../../src/utils/agent-message-runtime/AgentMessageProjectChange';
3
+ import { buildAgentProjectProfileHref } from '../agentProjects/agentProjectHrefs';
4
+ import { resolveAgentProjectInfo } from '../agentProjects/resolveAgentProjectInfo';
5
+ import { resolveAgentProjectRuntimeStatus } from '../agentProjects/resolveAgentProjectRuntimeStatus';
6
+ import { formatResourceBytes } from '../resourceMonitor/formatResourceMonitorValue';
7
+
8
+ /**
9
+ * Builds everything one project chip shows about the project it stands for.
10
+ *
11
+ * The payload is assembled from the very same sources as the project page — project metadata,
12
+ * runtime state and the formatted project size — so a chip and the page it links to can never
13
+ * describe one project differently. It travels inside the chat message, which keeps the chip
14
+ * popup readable in every chat surface without asking the server again.
15
+ *
16
+ * @param options - Project identity and what the answered message changed in it.
17
+ * @returns Chip payload, or `null` when the project no longer exists.
18
+ */
19
+ export async function createTouchedProjectChipResult(options: {
20
+ readonly agentPermanentId: string;
21
+ readonly projectName: string;
22
+ readonly projectChange: AgentMessageProjectChange | null;
23
+ }): Promise<AgentProjectToolCallResult | null> {
24
+ const project = await resolveAgentProjectInfo(options.agentPermanentId, options.projectName);
25
+
26
+ if (!project) {
27
+ return null;
28
+ }
29
+
30
+ const runtimeStatus = await resolveAgentProjectRuntimeStatus(options.agentPermanentId, project.projectName);
31
+
32
+ return {
33
+ projectName: project.projectName,
34
+ displayName: project.displayName,
35
+ projectHref: buildAgentProjectProfileHref(options.agentPermanentId, project.projectName),
36
+ isRunning: runtimeStatus.isRunning,
37
+ runtimeStatusLabel: runtimeStatus.statusLabel,
38
+ sizeLabel: formatResourceBytes(project.sizeBytes),
39
+ fileCount: project.fileCount,
40
+ isGitRepository: project.isGitRepository,
41
+ ...(project.description ? { description: project.description } : {}),
42
+ ...(runtimeStatus.projectUrl ? { projectUrl: runtimeStatus.projectUrl } : {}),
43
+ ...(options.projectChange ? { change: options.projectChange } : {}),
44
+ };
45
+ }
@@ -1,8 +1,8 @@
1
1
  import type { ToolCall } from '@promptbook-local/types';
2
2
  import { AGENT_PROJECT_TOOL_CALL_NAME } from '../../../../../src/book-components/Chat/utils/agentProjectToolCall';
3
- import { buildAgentProjectProfileHref } from '../agentProjects/agentProjectHrefs';
3
+ import type { AgentMessageProjectChange } from '../../../../../src/utils/agent-message-runtime/AgentMessageProjectChange';
4
4
  import { isSafeAgentProjectPathSegment } from '../agentProjects/agentProjectsPaths';
5
- import { resolveAgentProjectInfo } from '../agentProjects/resolveAgentProjectInfo';
5
+ import { createTouchedProjectChipResult } from './createTouchedProjectChipResult';
6
6
 
7
7
  /**
8
8
  * Prefix of the idempotency keys identifying touched-project chips.
@@ -13,27 +13,31 @@ const TOUCHED_PROJECT_CHIP_IDEMPOTENCY_PREFIX = 'agent-project';
13
13
  * Creates the project chips of one answered message.
14
14
  *
15
15
  * A project is reported by the runner once the answering harness viewed or edited any of its
16
- * files, and it is resolved here so the chip carries the same human-readable project name and
17
- * link as every other project surface. Projects that no longer exist are skipped.
16
+ * files, and every project the answer really committed something into is included as well a
17
+ * changed project was obviously worked with, even when nothing in the harness log said so.
18
+ * Projects that no longer exist are skipped.
18
19
  *
19
- * @param options - Owning agent and the project directory names its answer touched.
20
+ * @param options - Owning agent, the project directory names its answer touched and what it changed.
20
21
  * @returns Project tool calls shown as chips below the answer.
21
22
  */
22
23
  export async function createTouchedProjectChipToolCalls(options: {
23
24
  readonly agentPermanentId: string;
24
25
  readonly touchedProjectNames: ReadonlyArray<string>;
26
+ readonly projectChanges: ReadonlyArray<AgentMessageProjectChange>;
25
27
  readonly createdAt: NonNullable<ToolCall['createdAt']>;
26
28
  }): Promise<ReadonlyArray<ToolCall>> {
29
+ const changeByProjectName = new Map(
30
+ options.projectChanges.map((projectChange) => [projectChange.projectName.toLowerCase(), projectChange]),
31
+ );
27
32
  const projectChipToolCalls = await Promise.all(
28
- options.touchedProjectNames
29
- .filter((touchedProjectName) => isSafeAgentProjectPathSegment(touchedProjectName))
30
- .map((touchedProjectName) =>
31
- createTouchedProjectChipToolCall({
32
- agentPermanentId: options.agentPermanentId,
33
- projectName: touchedProjectName,
34
- createdAt: options.createdAt,
35
- }),
36
- ),
33
+ resolveChippedProjectNames(options.touchedProjectNames, options.projectChanges).map((projectName) =>
34
+ createTouchedProjectChipToolCall({
35
+ agentPermanentId: options.agentPermanentId,
36
+ projectName,
37
+ projectChange: changeByProjectName.get(projectName.toLowerCase()) || null,
38
+ createdAt: options.createdAt,
39
+ }),
40
+ ),
37
41
  );
38
42
 
39
43
  return projectChipToolCalls.filter((projectChipToolCall): projectChipToolCall is ToolCall =>
@@ -41,10 +45,39 @@ export async function createTouchedProjectChipToolCalls(options: {
41
45
  );
42
46
  }
43
47
 
48
+ /**
49
+ * Resolves which projects deserve a chip, keeping the order in which they were reported.
50
+ *
51
+ * @param touchedProjectNames - Projects the harness log showed as viewed or edited.
52
+ * @param projectChanges - Projects the answer committed something into.
53
+ * @returns Unique, safe project directory names.
54
+ *
55
+ * @private function of `createTouchedProjectChipToolCalls`
56
+ */
57
+ function resolveChippedProjectNames(
58
+ touchedProjectNames: ReadonlyArray<string>,
59
+ projectChanges: ReadonlyArray<AgentMessageProjectChange>,
60
+ ): ReadonlyArray<string> {
61
+ const chippedProjectNames = new Map<string, string>();
62
+
63
+ for (const projectName of [
64
+ ...touchedProjectNames,
65
+ ...projectChanges.map((projectChange) => projectChange.projectName),
66
+ ]) {
67
+ if (!isSafeAgentProjectPathSegment(projectName) || chippedProjectNames.has(projectName.toLowerCase())) {
68
+ continue;
69
+ }
70
+
71
+ chippedProjectNames.set(projectName.toLowerCase(), projectName);
72
+ }
73
+
74
+ return [...chippedProjectNames.values()];
75
+ }
76
+
44
77
  /**
45
78
  * Creates the chip of one touched project.
46
79
  *
47
- * @param options - Owning agent and one touched project directory name.
80
+ * @param options - Owning agent, one touched project and what the answer changed in it.
48
81
  * @returns Project tool call, or `null` when the project no longer exists.
49
82
  *
50
83
  * @private function of `createTouchedProjectChipToolCalls`
@@ -52,24 +85,25 @@ export async function createTouchedProjectChipToolCalls(options: {
52
85
  async function createTouchedProjectChipToolCall(options: {
53
86
  readonly agentPermanentId: string;
54
87
  readonly projectName: string;
88
+ readonly projectChange: AgentMessageProjectChange | null;
55
89
  readonly createdAt: NonNullable<ToolCall['createdAt']>;
56
90
  }): Promise<ToolCall | null> {
57
- const project = await resolveAgentProjectInfo(options.agentPermanentId, options.projectName);
91
+ const projectChipResult = await createTouchedProjectChipResult({
92
+ agentPermanentId: options.agentPermanentId,
93
+ projectName: options.projectName,
94
+ projectChange: options.projectChange,
95
+ });
58
96
 
59
- if (!project) {
97
+ if (!projectChipResult) {
60
98
  return null;
61
99
  }
62
100
 
63
101
  return {
64
102
  name: AGENT_PROJECT_TOOL_CALL_NAME,
65
- arguments: { projectName: project.projectName },
66
- result: {
67
- projectName: project.projectName,
68
- displayName: project.displayName,
69
- projectHref: buildAgentProjectProfileHref(options.agentPermanentId, project.projectName),
70
- },
103
+ arguments: { projectName: projectChipResult.projectName },
104
+ result: projectChipResult,
71
105
  state: 'COMPLETE',
72
- idempotencyKey: `${TOUCHED_PROJECT_CHIP_IDEMPOTENCY_PREFIX}-${project.projectName.toLowerCase()}`,
106
+ idempotencyKey: `${TOUCHED_PROJECT_CHIP_IDEMPOTENCY_PREFIX}-${projectChipResult.projectName.toLowerCase()}`,
73
107
  createdAt: options.createdAt,
74
108
  };
75
109
  }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Number of fields in a standard minute-based cron expression.
3
+ *
4
+ * @private constant of `cronExpression`
5
+ */
6
+ export const CRON_EXPRESSION_FIELD_COUNT = 5;
7
+
8
+ /**
9
+ * Parsed values of one cron field.
10
+ *
11
+ * @private type of `cronExpression`
12
+ */
13
+ export type CronExpressionField = {
14
+ /**
15
+ * Accepted numeric values for this field.
16
+ */
17
+ readonly values: ReadonlySet<number>;
18
+
19
+ /**
20
+ * Whether the field is the unrestricted `*` wildcard.
21
+ */
22
+ readonly isWildcard: boolean;
23
+ };
24
+
25
+ /**
26
+ * Parsed five-field cron expression.
27
+ *
28
+ * @private type of `cronExpression`
29
+ */
30
+ export type ParsedCronExpression = {
31
+ readonly minute: CronExpressionField;
32
+ readonly hour: CronExpressionField;
33
+ readonly dayOfMonth: CronExpressionField;
34
+ readonly month: CronExpressionField;
35
+ readonly dayOfWeek: CronExpressionField;
36
+ };
37
+
38
+ /**
39
+ * Parser configuration of one cron field.
40
+ *
41
+ * @private type of `cronExpression`
42
+ */
43
+ export type CronExpressionFieldOptions = {
44
+ /**
45
+ * Field name used in validation errors.
46
+ */
47
+ readonly name: string;
48
+
49
+ /**
50
+ * Lowest accepted value.
51
+ */
52
+ readonly minimum: number;
53
+
54
+ /**
55
+ * Highest accepted value.
56
+ */
57
+ readonly maximum: number;
58
+
59
+ /**
60
+ * Whether `7` is an alias of Sunday, which is only true for the day-of-week field.
61
+ */
62
+ readonly isSevenAllowedForSunday?: boolean;
63
+ };
@@ -0,0 +1,34 @@
1
+ import { spaceTrim } from 'spacetrim';
2
+ import { ParseError } from '../../../../../src/errors/ParseError';
3
+ import { normalizeCronExpressionWhitespace } from './normalizeCronExpressionWhitespace';
4
+ import { parseCronExpression } from './parseCronExpression';
5
+ import { resolveNextCronRunFromParsedExpression } from './resolveNextCronRun';
6
+
7
+ /**
8
+ * Normalizes and validates one cron expression.
9
+ *
10
+ * An expression which parses but never matches a real date, such as `0 0 30 2 *`, is rejected here
11
+ * instead of silently becoming a schedule that never runs.
12
+ *
13
+ * @param expression - Raw cron expression.
14
+ * @returns Whitespace-normalized expression.
15
+ *
16
+ * @private function of `cronExpression`
17
+ */
18
+ export function normalizeCronExpression(expression: string): string {
19
+ const normalizedExpression = normalizeCronExpressionWhitespace(expression);
20
+
21
+ if (normalizedExpression === '') {
22
+ throw new ParseError(
23
+ spaceTrim(`
24
+ Cron expression is empty.
25
+
26
+ **Use exactly five fields:** minute hour day-of-month month day-of-week.
27
+ `),
28
+ );
29
+ }
30
+
31
+ resolveNextCronRunFromParsedExpression(parseCronExpression(normalizedExpression), new Date());
32
+
33
+ return normalizedExpression;
34
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Collapses cron whitespace without changing any field value.
3
+ *
4
+ * @param expression - Raw cron expression.
5
+ * @returns Whitespace-normalized expression, which is empty when the input holds no field at all.
6
+ *
7
+ * @private function of `cronExpression`
8
+ */
9
+ export function normalizeCronExpressionWhitespace(expression: string): string {
10
+ return expression.trim().replace(/\s+/gu, ' ');
11
+ }
@@ -0,0 +1,41 @@
1
+ import { spaceTrim } from 'spacetrim';
2
+ import { ParseError } from '../../../../../src/errors/ParseError';
3
+ import { CRON_EXPRESSION_FIELD_COUNT, type ParsedCronExpression } from './CronExpression';
4
+ import { normalizeCronExpressionWhitespace } from './normalizeCronExpressionWhitespace';
5
+ import { parseCronExpressionField } from './parseCronExpressionField';
6
+
7
+ /**
8
+ * Parses one five-field cron expression into numeric field sets.
9
+ *
10
+ * @param expression - Raw cron expression, for example `15 9-17 * * 1-5`.
11
+ * @returns Parsed cron expression.
12
+ *
13
+ * @private function of `cronExpression`
14
+ */
15
+ export function parseCronExpression(expression: string): ParsedCronExpression {
16
+ const normalizedExpression = normalizeCronExpressionWhitespace(expression);
17
+ const fields = normalizedExpression.split(' ');
18
+
19
+ if (fields.length !== CRON_EXPRESSION_FIELD_COUNT) {
20
+ throw new ParseError(
21
+ spaceTrim(`
22
+ Cron expression \`${normalizedExpression}\` is invalid.
23
+
24
+ **Use exactly five fields:** minute hour day-of-month month day-of-week.
25
+ `),
26
+ );
27
+ }
28
+
29
+ return {
30
+ minute: parseCronExpressionField(fields[0]!, { name: 'minute', minimum: 0, maximum: 59 }),
31
+ hour: parseCronExpressionField(fields[1]!, { name: 'hour', minimum: 0, maximum: 23 }),
32
+ dayOfMonth: parseCronExpressionField(fields[2]!, { name: 'day-of-month', minimum: 1, maximum: 31 }),
33
+ month: parseCronExpressionField(fields[3]!, { name: 'month', minimum: 1, maximum: 12 }),
34
+ dayOfWeek: parseCronExpressionField(fields[4]!, {
35
+ name: 'day-of-week',
36
+ minimum: 0,
37
+ maximum: 7,
38
+ isSevenAllowedForSunday: true,
39
+ }),
40
+ };
41
+ }
@@ -0,0 +1,140 @@
1
+ import type { CronExpressionField, CronExpressionFieldOptions } from './CronExpression';
2
+ import { throwInvalidCronExpressionField } from './throwInvalidCronExpressionField';
3
+
4
+ /**
5
+ * Parses one cron field with comma lists, ranges, and step values.
6
+ *
7
+ * @param field - Raw field value.
8
+ * @param options - Numeric bounds and label of the field.
9
+ * @returns Parsed field values.
10
+ *
11
+ * @private function of `cronExpression`
12
+ */
13
+ export function parseCronExpressionField(field: string, options: CronExpressionFieldOptions): CronExpressionField {
14
+ const values = new Set<number>();
15
+ const isWildcard = field === '*';
16
+
17
+ for (const part of field.split(',')) {
18
+ if (!part) {
19
+ throwInvalidCronExpressionField(field, options.name);
20
+ }
21
+
22
+ addCronExpressionFieldPart(values, part, options);
23
+ }
24
+
25
+ if (values.size === 0) {
26
+ throwInvalidCronExpressionField(field, options.name);
27
+ }
28
+
29
+ return { values, isWildcard };
30
+ }
31
+
32
+ /**
33
+ * Adds the values represented by one comma-separated cron field part.
34
+ *
35
+ * @param values - Mutable field value set.
36
+ * @param part - Field part, for example a wildcard, `1-5`, or a stepped wildcard.
37
+ * @param options - Numeric bounds and label of the field.
38
+ *
39
+ * @private function of `parseCronExpressionField`
40
+ */
41
+ function addCronExpressionFieldPart(values: Set<number>, part: string, options: CronExpressionFieldOptions): void {
42
+ const stepSplit = part.split('/');
43
+ if (stepSplit.length > 2) {
44
+ throwInvalidCronExpressionField(part, options.name);
45
+ }
46
+
47
+ const rangePart = stepSplit[0]!;
48
+ const step = stepSplit[1] === undefined ? 1 : parseCronExpressionNumber(stepSplit[1], options.name);
49
+ if (step <= 0) {
50
+ throwInvalidCronExpressionField(part, options.name);
51
+ }
52
+
53
+ const { start, end } = parseCronExpressionRange(rangePart, options);
54
+ for (let value = start; value <= end; value += step) {
55
+ values.add(normalizeCronExpressionFieldValue(value, options));
56
+ }
57
+ }
58
+
59
+ /**
60
+ * Parses the range portion of one cron field part.
61
+ *
62
+ * @param rangePart - Range part before the optional `/step`.
63
+ * @param options - Numeric bounds and label of the field.
64
+ * @returns Start and end range values.
65
+ *
66
+ * @private function of `parseCronExpressionField`
67
+ */
68
+ function parseCronExpressionRange(
69
+ rangePart: string,
70
+ options: CronExpressionFieldOptions,
71
+ ): { readonly start: number; readonly end: number } {
72
+ if (rangePart === '*') {
73
+ return { start: options.minimum, end: options.maximum };
74
+ }
75
+
76
+ const rangeSplit = rangePart.split('-');
77
+ if (rangeSplit.length > 2 || rangeSplit.some((value) => value === '')) {
78
+ throwInvalidCronExpressionField(rangePart, options.name);
79
+ }
80
+
81
+ const start = parseCronExpressionNumber(rangeSplit[0]!, options.name);
82
+ const end = rangeSplit[1] === undefined ? start : parseCronExpressionNumber(rangeSplit[1], options.name);
83
+
84
+ if (start > end) {
85
+ throwInvalidCronExpressionField(rangePart, options.name);
86
+ }
87
+
88
+ assertCronExpressionFieldValueInRange(start, options);
89
+ assertCronExpressionFieldValueInRange(end, options);
90
+
91
+ return { start, end };
92
+ }
93
+
94
+ /**
95
+ * Parses one positive cron integer token.
96
+ *
97
+ * @param value - Raw token.
98
+ * @param fieldName - Field name used in validation errors.
99
+ * @returns Parsed integer.
100
+ *
101
+ * @private function of `parseCronExpressionField`
102
+ */
103
+ function parseCronExpressionNumber(value: string, fieldName: string): number {
104
+ if (!/^\d+$/u.test(value)) {
105
+ throwInvalidCronExpressionField(value, fieldName);
106
+ }
107
+
108
+ return Number.parseInt(value, 10);
109
+ }
110
+
111
+ /**
112
+ * Asserts that one parsed cron value is inside the field bounds.
113
+ *
114
+ * @param value - Parsed value.
115
+ * @param options - Numeric bounds and label of the field.
116
+ *
117
+ * @private function of `parseCronExpressionField`
118
+ */
119
+ function assertCronExpressionFieldValueInRange(value: number, options: CronExpressionFieldOptions): void {
120
+ if (value < options.minimum || value > options.maximum) {
121
+ throwInvalidCronExpressionField(String(value), options.name);
122
+ }
123
+ }
124
+
125
+ /**
126
+ * Normalizes Sunday from `7` to `0` in the day-of-week field.
127
+ *
128
+ * @param value - Parsed field value.
129
+ * @param options - Numeric bounds and label of the field.
130
+ * @returns Normalized value.
131
+ *
132
+ * @private function of `parseCronExpressionField`
133
+ */
134
+ function normalizeCronExpressionFieldValue(value: number, options: CronExpressionFieldOptions): number {
135
+ if (options.isSevenAllowedForSunday && value === 7) {
136
+ return 0;
137
+ }
138
+
139
+ return value;
140
+ }