@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.
- 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 +951 -102
- 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/scripts/run-codex-prompts/ping/pingCoderHarnessPeriodically.d.ts +22 -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/cli/cli-commands/coder/waitOptions.d.ts +12 -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/coder/ping.ts +35 -9
- package/src/cli/cli-commands/coder/waitOptions.ts +33 -0
- 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 +819 -751
- 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 +950 -101
- 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/scripts/run-codex-prompts/ping/pingCoderHarnessPeriodically.d.ts +22 -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/cli/cli-commands/coder/waitOptions.d.ts +12 -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
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { resolveAgentProjectRuntimeEnvironmentFlag } from './resolveAgentProjectRuntimeEnvironmentFlag';
|
|
2
|
+
import { startDefaultAgentProjectRuntimes } from './startDefaultAgentProjectRuntimes';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Environment variable that can force-enable or force-disable starting projects automatically.
|
|
6
|
+
*/
|
|
7
|
+
export const PTBK_AGENT_PROJECT_RUNTIME_AUTOSTART_ENABLED_ENV = 'PTBK_AGENT_PROJECT_RUNTIME_AUTOSTART_ENABLED';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Global key used to keep one automatic project-start scheduler per Node.js process.
|
|
11
|
+
*/
|
|
12
|
+
const AGENT_PROJECT_RUNTIME_AUTOSTART_SCHEDULER_GLOBAL_KEY = '__PROMPTBOOK_AGENT_PROJECT_RUNTIME_AUTOSTART__';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* How often the server checks whether every project is in the state it is expected to be in.
|
|
16
|
+
*
|
|
17
|
+
* Five minutes is short enough for a freshly created project and for a crashed one to come back
|
|
18
|
+
* without anybody pressing a button, and long enough that a project which cannot start is retried
|
|
19
|
+
* rarely instead of constantly.
|
|
20
|
+
*/
|
|
21
|
+
export const AGENT_PROJECT_RUNTIME_AUTOSTART_INTERVAL_MS = 5 * 60 * 1000;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Scheduler state stored on `globalThis` to survive module reloads.
|
|
25
|
+
*/
|
|
26
|
+
type AgentProjectRuntimeAutostartSchedulerState = {
|
|
27
|
+
/**
|
|
28
|
+
* Whether the scheduler has been bootstrapped in this process.
|
|
29
|
+
*/
|
|
30
|
+
isBootstrapped: boolean;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Whether one pass is currently running.
|
|
34
|
+
*/
|
|
35
|
+
isRunning: boolean;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Pending timer, if any.
|
|
39
|
+
*/
|
|
40
|
+
timeout: NodeJS.Timeout | null;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Global object shape used for process-wide scheduler state.
|
|
45
|
+
*/
|
|
46
|
+
type AgentProjectRuntimeAutostartSchedulerGlobal = typeof globalThis & {
|
|
47
|
+
[AGENT_PROJECT_RUNTIME_AUTOSTART_SCHEDULER_GLOBAL_KEY]?: AgentProjectRuntimeAutostartSchedulerState;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Starts all projects which are expected to be running and keeps them that way.
|
|
52
|
+
*
|
|
53
|
+
* The first pass runs immediately but never blocks the caller, so a restarted server serves its
|
|
54
|
+
* first request while the projects behind it are coming up.
|
|
55
|
+
*/
|
|
56
|
+
export function ensureAgentProjectRuntimeAutostartBootstrapped(): void {
|
|
57
|
+
if (!isAgentProjectRuntimeAutostartAvailable()) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const state = getAgentProjectRuntimeAutostartSchedulerState();
|
|
62
|
+
if (state.isBootstrapped) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
state.isBootstrapped = true;
|
|
67
|
+
void runAgentProjectRuntimeAutostartPass();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Schedules the next pass.
|
|
72
|
+
*/
|
|
73
|
+
function scheduleNextAgentProjectRuntimeAutostartPass(): void {
|
|
74
|
+
const state = getAgentProjectRuntimeAutostartSchedulerState();
|
|
75
|
+
clearAgentProjectRuntimeAutostartTimer(state);
|
|
76
|
+
|
|
77
|
+
state.timeout = setTimeout(() => {
|
|
78
|
+
void runAgentProjectRuntimeAutostartPass();
|
|
79
|
+
}, AGENT_PROJECT_RUNTIME_AUTOSTART_INTERVAL_MS);
|
|
80
|
+
state.timeout.unref?.();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Runs one pass and reschedules the next one.
|
|
85
|
+
*
|
|
86
|
+
* Every failure only logs and never throws: a project which cannot be started must never take down
|
|
87
|
+
* the scheduler or the running server.
|
|
88
|
+
*/
|
|
89
|
+
async function runAgentProjectRuntimeAutostartPass(): Promise<void> {
|
|
90
|
+
const state = getAgentProjectRuntimeAutostartSchedulerState();
|
|
91
|
+
if (state.isRunning) {
|
|
92
|
+
scheduleNextAgentProjectRuntimeAutostartPass();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
state.isRunning = true;
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
const report = await startDefaultAgentProjectRuntimes();
|
|
100
|
+
|
|
101
|
+
if (report.startedProjectCount > 0 || report.failedProjectCount > 0) {
|
|
102
|
+
console.info(
|
|
103
|
+
`🚀 Started ${report.startedProjectCount} agent project(s), ${report.runningProjectCount} already running, ${report.stoppedProjectCount} left stopped, ${report.failedProjectCount} failed.`,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error('[agent-project-runtimes] automatic project start failed', error);
|
|
108
|
+
} finally {
|
|
109
|
+
state.isRunning = false;
|
|
110
|
+
scheduleNextAgentProjectRuntimeAutostartPass();
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Clears one pending scheduler timer.
|
|
116
|
+
*
|
|
117
|
+
* @param state - Process-wide scheduler state.
|
|
118
|
+
*/
|
|
119
|
+
function clearAgentProjectRuntimeAutostartTimer(state: AgentProjectRuntimeAutostartSchedulerState): void {
|
|
120
|
+
if (!state.timeout) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
clearTimeout(state.timeout);
|
|
125
|
+
state.timeout = null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Returns process-wide scheduler state.
|
|
130
|
+
*
|
|
131
|
+
* @returns Mutable scheduler state.
|
|
132
|
+
*/
|
|
133
|
+
function getAgentProjectRuntimeAutostartSchedulerState(): AgentProjectRuntimeAutostartSchedulerState {
|
|
134
|
+
const schedulerGlobal = globalThis as AgentProjectRuntimeAutostartSchedulerGlobal;
|
|
135
|
+
schedulerGlobal[AGENT_PROJECT_RUNTIME_AUTOSTART_SCHEDULER_GLOBAL_KEY] ??= {
|
|
136
|
+
isBootstrapped: false,
|
|
137
|
+
isRunning: false,
|
|
138
|
+
timeout: null,
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return schedulerGlobal[AGENT_PROJECT_RUNTIME_AUTOSTART_SCHEDULER_GLOBAL_KEY]!;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Returns whether the current process should start projects automatically.
|
|
146
|
+
*
|
|
147
|
+
* Projects are server-owned processes, so they are only started from a real Node.js server process,
|
|
148
|
+
* never during tests or the Next.js production build.
|
|
149
|
+
*
|
|
150
|
+
* @returns `true` when this process may own project runtimes.
|
|
151
|
+
*/
|
|
152
|
+
function isAgentProjectRuntimeAutostartAvailable(): boolean {
|
|
153
|
+
if (process.env.NODE_ENV === 'test' || process.env.JEST_WORKER_ID !== undefined) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (process.env.NEXT_PHASE === 'phase-production-build') {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return resolveAgentProjectRuntimeEnvironmentFlag(PTBK_AGENT_PROJECT_RUNTIME_AUTOSTART_ENABLED_ENV) ?? true;
|
|
162
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from 'fs/promises';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { UnexpectedError } from '../../../../../src/errors/UnexpectedError';
|
|
4
|
+
import { spaceTrim } from '../../../../../src/utils/organization/spaceTrim';
|
|
5
|
+
import { isSameAgentProjectIdentity, type AgentProjectIdentity } from './agentProjectIdentity';
|
|
6
|
+
import { resolveAgentProjectRuntimeDesiredStateFilePath } from './agentProjectRuntimePaths';
|
|
7
|
+
import { runAgentProjectStateMutation } from './agentProjectStateMutationQueue';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* States one agent project can be asked to be in.
|
|
11
|
+
*/
|
|
12
|
+
export const AGENT_PROJECT_RUNTIME_DESIRED_STATES = ['running', 'stopped'] as const;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* State one agent project is expected to be in until somebody decides otherwise.
|
|
16
|
+
*/
|
|
17
|
+
export type AgentProjectRuntimeDesiredState = (typeof AGENT_PROJECT_RUNTIME_DESIRED_STATES)[number];
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* State of every project which was never explicitly stopped.
|
|
21
|
+
*
|
|
22
|
+
* A project exists to be reachable, so being started is its default — only an explicit stop
|
|
23
|
+
* keeps it down across server restarts.
|
|
24
|
+
*/
|
|
25
|
+
export const DEFAULT_AGENT_PROJECT_RUNTIME_DESIRED_STATE: AgentProjectRuntimeDesiredState = 'running';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Global key used to serialize desired-state mutations across concurrent requests.
|
|
29
|
+
*/
|
|
30
|
+
const AGENT_PROJECT_RUNTIME_DESIRED_STATE_GLOBAL_KEY = '__PROMPTBOOK_AGENT_PROJECT_RUNTIME_DESIRED_STATE__';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Current persisted desired-state schema version.
|
|
34
|
+
*/
|
|
35
|
+
const AGENT_PROJECT_RUNTIME_DESIRED_STATE_VERSION = 1;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Persisted decision to run or not to run one agent project.
|
|
39
|
+
*/
|
|
40
|
+
export type AgentProjectRuntimeDesiredStateRecord = AgentProjectIdentity & {
|
|
41
|
+
/**
|
|
42
|
+
* State the project should be in.
|
|
43
|
+
*/
|
|
44
|
+
readonly desiredState: AgentProjectRuntimeDesiredState;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* ISO timestamp when this decision was made.
|
|
48
|
+
*/
|
|
49
|
+
readonly updatedAt: string;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Persisted desired-state document shape.
|
|
54
|
+
*/
|
|
55
|
+
type PersistedAgentProjectRuntimeDesiredStates = {
|
|
56
|
+
readonly version: number;
|
|
57
|
+
readonly projects: ReadonlyArray<AgentProjectRuntimeDesiredStateRecord>;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Lists every explicit decision to run or not to run a project.
|
|
62
|
+
*
|
|
63
|
+
* Projects nobody ever started or stopped are absent from the list — they run by default.
|
|
64
|
+
*
|
|
65
|
+
* @returns Persisted desired-state records.
|
|
66
|
+
*/
|
|
67
|
+
export async function listAgentProjectRuntimeDesiredStates(): Promise<
|
|
68
|
+
ReadonlyArray<AgentProjectRuntimeDesiredStateRecord>
|
|
69
|
+
> {
|
|
70
|
+
const desiredStateFilePath = resolveAgentProjectRuntimeDesiredStateFilePath();
|
|
71
|
+
let rawContent: string;
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
rawContent = await readFile(desiredStateFilePath, 'utf-8');
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
77
|
+
return [];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
throw new UnexpectedError(
|
|
81
|
+
spaceTrim(`
|
|
82
|
+
Failed to read agent project desired states.
|
|
83
|
+
|
|
84
|
+
**Desired state file:** \`${desiredStateFilePath}\`
|
|
85
|
+
**Cause:** \`${error instanceof Error ? error.message : String(error)}\`
|
|
86
|
+
`),
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
return parsePersistedAgentProjectRuntimeDesiredStates(JSON.parse(rawContent));
|
|
92
|
+
} catch (error) {
|
|
93
|
+
throw new UnexpectedError(
|
|
94
|
+
spaceTrim(`
|
|
95
|
+
Failed to parse agent project desired states.
|
|
96
|
+
|
|
97
|
+
**Desired state file:** \`${desiredStateFilePath}\`
|
|
98
|
+
**Cause:** \`${error instanceof Error ? error.message : String(error)}\`
|
|
99
|
+
`),
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Resolves the desired state of one project from already-loaded records.
|
|
106
|
+
*
|
|
107
|
+
* This is the one place deciding what "no record at all" means, so a caller which reads every
|
|
108
|
+
* record once — such as the automatic project start — answers the same question the same way.
|
|
109
|
+
*
|
|
110
|
+
* @param desiredStateRecords - Persisted desired-state records.
|
|
111
|
+
* @param identity - Agent and project identification.
|
|
112
|
+
* @returns State the project should be in.
|
|
113
|
+
*/
|
|
114
|
+
export function resolveAgentProjectRuntimeDesiredStateFromRecords(
|
|
115
|
+
desiredStateRecords: ReadonlyArray<AgentProjectRuntimeDesiredStateRecord>,
|
|
116
|
+
identity: AgentProjectIdentity,
|
|
117
|
+
): AgentProjectRuntimeDesiredState {
|
|
118
|
+
const desiredStateRecord = desiredStateRecords.find((record) => isSameAgentProjectIdentity(record, identity));
|
|
119
|
+
|
|
120
|
+
return desiredStateRecord?.desiredState ?? DEFAULT_AGENT_PROJECT_RUNTIME_DESIRED_STATE;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Resolves the desired state of one single project.
|
|
125
|
+
*
|
|
126
|
+
* @param identity - Agent and project identification.
|
|
127
|
+
* @returns State the project should be in.
|
|
128
|
+
*/
|
|
129
|
+
export async function resolveAgentProjectRuntimeDesiredState(
|
|
130
|
+
identity: AgentProjectIdentity,
|
|
131
|
+
): Promise<AgentProjectRuntimeDesiredState> {
|
|
132
|
+
return resolveAgentProjectRuntimeDesiredStateFromRecords(await listAgentProjectRuntimeDesiredStates(), identity);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Remembers that one project should be running or should stay stopped.
|
|
137
|
+
*
|
|
138
|
+
* Nothing is written when the project is already expected to be in the requested state, so a
|
|
139
|
+
* project which simply runs by default never grows a record of its own.
|
|
140
|
+
*
|
|
141
|
+
* @param options - Agent and project identification together with the requested state.
|
|
142
|
+
*/
|
|
143
|
+
export async function setAgentProjectRuntimeDesiredState(
|
|
144
|
+
options: AgentProjectIdentity & {
|
|
145
|
+
/**
|
|
146
|
+
* State the project should be in from now on.
|
|
147
|
+
*/
|
|
148
|
+
readonly desiredState: AgentProjectRuntimeDesiredState;
|
|
149
|
+
},
|
|
150
|
+
): Promise<void> {
|
|
151
|
+
await runAgentProjectStateMutation(AGENT_PROJECT_RUNTIME_DESIRED_STATE_GLOBAL_KEY, async () => {
|
|
152
|
+
const desiredStateRecords = await listAgentProjectRuntimeDesiredStates();
|
|
153
|
+
|
|
154
|
+
if (resolveAgentProjectRuntimeDesiredStateFromRecords(desiredStateRecords, options) === options.desiredState) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const changedRecord: AgentProjectRuntimeDesiredStateRecord = {
|
|
159
|
+
agentPermanentId: options.agentPermanentId,
|
|
160
|
+
projectName: options.projectName,
|
|
161
|
+
desiredState: options.desiredState,
|
|
162
|
+
updatedAt: new Date().toISOString(),
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
await writeAgentProjectRuntimeDesiredStates([
|
|
166
|
+
...desiredStateRecords.filter((record) => !isSameAgentProjectIdentity(record, options)),
|
|
167
|
+
changedRecord,
|
|
168
|
+
]);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Persists all desired-state records.
|
|
174
|
+
*
|
|
175
|
+
* @param desiredStateRecords - Records to persist.
|
|
176
|
+
*/
|
|
177
|
+
async function writeAgentProjectRuntimeDesiredStates(
|
|
178
|
+
desiredStateRecords: ReadonlyArray<AgentProjectRuntimeDesiredStateRecord>,
|
|
179
|
+
): Promise<void> {
|
|
180
|
+
const desiredStateFilePath = resolveAgentProjectRuntimeDesiredStateFilePath();
|
|
181
|
+
const payload: PersistedAgentProjectRuntimeDesiredStates = {
|
|
182
|
+
version: AGENT_PROJECT_RUNTIME_DESIRED_STATE_VERSION,
|
|
183
|
+
projects: [...desiredStateRecords].sort((firstRecord, secondRecord) =>
|
|
184
|
+
`${firstRecord.agentPermanentId}/${firstRecord.projectName}`.localeCompare(
|
|
185
|
+
`${secondRecord.agentPermanentId}/${secondRecord.projectName}`,
|
|
186
|
+
),
|
|
187
|
+
),
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
await mkdir(dirname(desiredStateFilePath), { recursive: true });
|
|
192
|
+
await writeFile(desiredStateFilePath, `${JSON.stringify(payload, null, 4)}\n`, 'utf-8');
|
|
193
|
+
} catch (error) {
|
|
194
|
+
throw new UnexpectedError(
|
|
195
|
+
spaceTrim(`
|
|
196
|
+
Failed to persist agent project desired states.
|
|
197
|
+
|
|
198
|
+
**Desired state file:** \`${desiredStateFilePath}\`
|
|
199
|
+
**Cause:** \`${error instanceof Error ? error.message : String(error)}\`
|
|
200
|
+
`),
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Parses persisted desired-state records and ignores invalid rows.
|
|
207
|
+
*/
|
|
208
|
+
function parsePersistedAgentProjectRuntimeDesiredStates(
|
|
209
|
+
rawValue: unknown,
|
|
210
|
+
): ReadonlyArray<AgentProjectRuntimeDesiredStateRecord> {
|
|
211
|
+
if (!rawValue || typeof rawValue !== 'object') {
|
|
212
|
+
return [];
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const desiredStates = rawValue as Partial<PersistedAgentProjectRuntimeDesiredStates>;
|
|
216
|
+
|
|
217
|
+
if (!Array.isArray(desiredStates.projects)) {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return desiredStates.projects
|
|
222
|
+
.map((rawRecord): AgentProjectRuntimeDesiredStateRecord | null => {
|
|
223
|
+
if (!rawRecord || typeof rawRecord !== 'object') {
|
|
224
|
+
return null;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const record = rawRecord as Partial<AgentProjectRuntimeDesiredStateRecord>;
|
|
228
|
+
|
|
229
|
+
if (
|
|
230
|
+
typeof record.agentPermanentId !== 'string' ||
|
|
231
|
+
typeof record.projectName !== 'string' ||
|
|
232
|
+
!isAgentProjectRuntimeDesiredState(record.desiredState)
|
|
233
|
+
) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
agentPermanentId: record.agentPermanentId,
|
|
239
|
+
projectName: record.projectName,
|
|
240
|
+
desiredState: record.desiredState,
|
|
241
|
+
updatedAt: typeof record.updatedAt === 'string' ? record.updatedAt : new Date(0).toISOString(),
|
|
242
|
+
};
|
|
243
|
+
})
|
|
244
|
+
.filter((record): record is AgentProjectRuntimeDesiredStateRecord => record !== null);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Checks whether a raw value is a known desired state.
|
|
249
|
+
*/
|
|
250
|
+
function isAgentProjectRuntimeDesiredState(value: unknown): value is AgentProjectRuntimeDesiredState {
|
|
251
|
+
return AGENT_PROJECT_RUNTIME_DESIRED_STATES.includes(value as AgentProjectRuntimeDesiredState);
|
|
252
|
+
}
|
|
@@ -21,10 +21,14 @@ export function formatAgentProjectRuntimeMode(mode: AgentProjectRuntimeMode): st
|
|
|
21
21
|
/**
|
|
22
22
|
* Formats one project runtime status for UI display.
|
|
23
23
|
*
|
|
24
|
-
* @param runtime - Runtime info.
|
|
24
|
+
* @param runtime - Runtime info, or `null` for a project which has no runtime at all.
|
|
25
25
|
* @returns Human-readable status label.
|
|
26
26
|
*/
|
|
27
|
-
export function formatAgentProjectRuntimeStatus(runtime: AgentProjectRuntimeInfo): string {
|
|
27
|
+
export function formatAgentProjectRuntimeStatus(runtime: AgentProjectRuntimeInfo | null): string {
|
|
28
|
+
if (!runtime) {
|
|
29
|
+
return 'Not running';
|
|
30
|
+
}
|
|
31
|
+
|
|
28
32
|
if (runtime.isRunning) {
|
|
29
33
|
return 'Running';
|
|
30
34
|
}
|
|
@@ -39,4 +43,3 @@ export function formatAgentProjectRuntimeStatus(runtime: AgentProjectRuntimeInfo
|
|
|
39
43
|
|
|
40
44
|
return 'Stopped';
|
|
41
45
|
}
|
|
42
|
-
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
resolveAgentProjectDomainRegistryFilePath,
|
|
10
10
|
resolveAgentProjectDomainsFilePath,
|
|
11
11
|
} from './agentProjectRuntimePaths';
|
|
12
|
+
import { runAgentProjectStateMutation } from './agentProjectStateMutationQueue';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Current on-disk domain registry schema version.
|
|
@@ -139,23 +140,6 @@ type PersistedAgentProjectDomainRegistry = {
|
|
|
139
140
|
readonly domains: ReadonlyArray<AgentProjectDomainRecord>;
|
|
140
141
|
};
|
|
141
142
|
|
|
142
|
-
/**
|
|
143
|
-
* Process-wide domain registry state.
|
|
144
|
-
*/
|
|
145
|
-
type AgentProjectDomainRegistryState = {
|
|
146
|
-
/**
|
|
147
|
-
* Promise chain used as a lightweight mutation queue.
|
|
148
|
-
*/
|
|
149
|
-
domainMutationQueue: Promise<void>;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Global object shape used for process-wide domain registry state.
|
|
154
|
-
*/
|
|
155
|
-
type AgentProjectDomainRegistryGlobal = typeof globalThis & {
|
|
156
|
-
[AGENT_PROJECT_DOMAIN_REGISTRY_GLOBAL_KEY]?: AgentProjectDomainRegistryState;
|
|
157
|
-
};
|
|
158
|
-
|
|
159
143
|
/**
|
|
160
144
|
* Assigns or refreshes the stable public domain for one agent project.
|
|
161
145
|
*
|
|
@@ -483,21 +467,7 @@ async function writeAgentProjectDomainRecords(records: ReadonlyArray<AgentProjec
|
|
|
483
467
|
* Runs one domain-registry mutation after previous mutations have finished.
|
|
484
468
|
*/
|
|
485
469
|
async function runAgentProjectDomainRegistryMutation<TValue>(operation: () => Promise<TValue>): Promise<TValue> {
|
|
486
|
-
|
|
487
|
-
const previousMutation = registryState.domainMutationQueue;
|
|
488
|
-
let releaseMutation!: () => void;
|
|
489
|
-
|
|
490
|
-
registryState.domainMutationQueue = new Promise<void>((resolve) => {
|
|
491
|
-
releaseMutation = resolve;
|
|
492
|
-
});
|
|
493
|
-
|
|
494
|
-
await previousMutation.catch(() => undefined);
|
|
495
|
-
|
|
496
|
-
try {
|
|
497
|
-
return await operation();
|
|
498
|
-
} finally {
|
|
499
|
-
releaseMutation();
|
|
500
|
-
}
|
|
470
|
+
return await runAgentProjectStateMutation(AGENT_PROJECT_DOMAIN_REGISTRY_GLOBAL_KEY, operation);
|
|
501
471
|
}
|
|
502
472
|
|
|
503
473
|
/**
|
|
@@ -719,15 +689,3 @@ async function writeTextFile(filePath: string, content: string): Promise<void> {
|
|
|
719
689
|
await mkdir(dirname(filePath), { recursive: true });
|
|
720
690
|
await writeFile(filePath, content, 'utf-8');
|
|
721
691
|
}
|
|
722
|
-
|
|
723
|
-
/**
|
|
724
|
-
* Returns process-wide project-domain registry state.
|
|
725
|
-
*/
|
|
726
|
-
function getAgentProjectDomainRegistryState(): AgentProjectDomainRegistryState {
|
|
727
|
-
const registryGlobal = globalThis as AgentProjectDomainRegistryGlobal;
|
|
728
|
-
registryGlobal[AGENT_PROJECT_DOMAIN_REGISTRY_GLOBAL_KEY] ??= {
|
|
729
|
-
domainMutationQueue: Promise.resolve(),
|
|
730
|
-
};
|
|
731
|
-
|
|
732
|
-
return registryGlobal[AGENT_PROJECT_DOMAIN_REGISTRY_GLOBAL_KEY]!;
|
|
733
|
-
}
|
|
@@ -15,6 +15,11 @@ export const PTBK_AGENT_PROJECT_DOMAIN_REGISTRY_FILE_ENV = 'PTBK_AGENT_PROJECT_D
|
|
|
15
15
|
*/
|
|
16
16
|
export const PTBK_AGENT_PROJECT_DOMAINS_FILE_ENV = 'PTBK_AGENT_PROJECT_DOMAINS_FILE';
|
|
17
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Environment variable overriding the persisted project desired-state file.
|
|
20
|
+
*/
|
|
21
|
+
export const PTBK_AGENT_PROJECT_RUNTIME_DESIRED_STATE_FILE_ENV = 'PTBK_AGENT_PROJECT_RUNTIME_DESIRED_STATE_FILE';
|
|
22
|
+
|
|
18
23
|
/**
|
|
19
24
|
* Directory under the Agents Server data root used for project runtime state.
|
|
20
25
|
*/
|
|
@@ -35,6 +40,11 @@ const AGENT_PROJECT_DOMAIN_REGISTRY_FILE_NAME = 'domains.json';
|
|
|
35
40
|
*/
|
|
36
41
|
const AGENT_PROJECT_DOMAINS_FILE_NAME = 'domains.txt';
|
|
37
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Persisted desired-state filename.
|
|
45
|
+
*/
|
|
46
|
+
const AGENT_PROJECT_RUNTIME_DESIRED_STATE_FILE_NAME = 'desired-states.json';
|
|
47
|
+
|
|
38
48
|
/**
|
|
39
49
|
* Resolves the durable state root used by agent project runtime managers.
|
|
40
50
|
*
|
|
@@ -86,6 +96,21 @@ export function resolveAgentProjectDomainRegistryFilePath(): string {
|
|
|
86
96
|
return join(resolveAgentProjectRuntimeStateRoot(), AGENT_PROJECT_DOMAIN_REGISTRY_FILE_NAME);
|
|
87
97
|
}
|
|
88
98
|
|
|
99
|
+
/**
|
|
100
|
+
* Resolves the JSON file remembering which projects were explicitly started or stopped.
|
|
101
|
+
*
|
|
102
|
+
* @returns Absolute file path.
|
|
103
|
+
*/
|
|
104
|
+
export function resolveAgentProjectRuntimeDesiredStateFilePath(): string {
|
|
105
|
+
const configuredFilePath = process.env[PTBK_AGENT_PROJECT_RUNTIME_DESIRED_STATE_FILE_ENV]?.trim();
|
|
106
|
+
|
|
107
|
+
if (configuredFilePath) {
|
|
108
|
+
return resolve(configuredFilePath);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return join(resolveAgentProjectRuntimeStateRoot(), AGENT_PROJECT_RUNTIME_DESIRED_STATE_FILE_NAME);
|
|
112
|
+
}
|
|
113
|
+
|
|
89
114
|
/**
|
|
90
115
|
* Resolves the newline-separated domain file consumed by the VPS installer.
|
|
91
116
|
*
|
|
@@ -3,6 +3,7 @@ import { createHash } from 'crypto';
|
|
|
3
3
|
import { promisify } from 'util';
|
|
4
4
|
import { AGENT_PROJECT_RUNTIME_HOST } from './agentProjectRuntimeConstants';
|
|
5
5
|
import type { AgentProjectRuntimeMode } from './AgentProjectRuntimeInfo';
|
|
6
|
+
import { resolveAgentProjectRuntimeEnvironmentFlag } from './resolveAgentProjectRuntimeEnvironmentFlag';
|
|
6
7
|
|
|
7
8
|
const execFileAsync = promisify(execFile);
|
|
8
9
|
|
|
@@ -137,10 +138,10 @@ export type StartAgentProjectRuntimePm2ProcessOptions = {
|
|
|
137
138
|
* @returns `true` on production Linux unless explicitly disabled.
|
|
138
139
|
*/
|
|
139
140
|
export function isAgentProjectRuntimePm2Enabled(): boolean {
|
|
140
|
-
const
|
|
141
|
+
const configuredFlag = resolveAgentProjectRuntimeEnvironmentFlag(PTBK_AGENT_PROJECT_RUNTIME_PM2_ENABLED_ENV);
|
|
141
142
|
|
|
142
|
-
if (
|
|
143
|
-
return
|
|
143
|
+
if (configuredFlag !== null) {
|
|
144
|
+
return configuredFlag;
|
|
144
145
|
}
|
|
145
146
|
|
|
146
147
|
return process.platform === 'linux' && process.env.NODE_ENV === 'production';
|