@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
package/umd/index.umd.js
CHANGED
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
* @generated
|
|
59
59
|
* @see https://github.com/webgptorg/promptbook
|
|
60
60
|
*/
|
|
61
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-
|
|
61
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-18';
|
|
62
62
|
/**
|
|
63
63
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
64
64
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -2217,7 +2217,7 @@
|
|
|
2217
2217
|
*/
|
|
2218
2218
|
async function ensureDirectory(projectPath, relativeDirectoryPath) {
|
|
2219
2219
|
const directoryPath = path.join(projectPath, relativeDirectoryPath);
|
|
2220
|
-
const isDirectoryExisting = await isExistingDirectory$
|
|
2220
|
+
const isDirectoryExisting = await isExistingDirectory$2(directoryPath);
|
|
2221
2221
|
if (!isDirectoryExisting) {
|
|
2222
2222
|
await promises.mkdir(directoryPath, { recursive: true });
|
|
2223
2223
|
return 'created';
|
|
@@ -2227,7 +2227,7 @@
|
|
|
2227
2227
|
/**
|
|
2228
2228
|
* Checks whether a path exists and is a directory.
|
|
2229
2229
|
*/
|
|
2230
|
-
async function isExistingDirectory$
|
|
2230
|
+
async function isExistingDirectory$2(path) {
|
|
2231
2231
|
try {
|
|
2232
2232
|
return (await promises.stat(path)).isDirectory();
|
|
2233
2233
|
}
|
|
@@ -5726,6 +5726,12 @@
|
|
|
5726
5726
|
|
|
5727
5727
|
Inherits agent source from another agent.
|
|
5728
5728
|
|
|
5729
|
+
Every agent inherits from the core agent \`@Adam\` unless it says otherwise, so writing no ${this.type} at all
|
|
5730
|
+
is the same as writing \`${this.type} @Adam\`. Write \`${this.type} @Null\` to inherit from nothing.
|
|
5731
|
+
|
|
5732
|
+
An agent has exactly one parent, so when ${this.type} is written more than once, the last one wins and
|
|
5733
|
+
overrides every earlier one.
|
|
5734
|
+
|
|
5729
5735
|
## Examples
|
|
5730
5736
|
|
|
5731
5737
|
\`\`\`book
|
|
@@ -5734,6 +5740,13 @@
|
|
|
5734
5740
|
FROM https://s6.ptbk.io/benjamin-white
|
|
5735
5741
|
RULE Speak only in English.
|
|
5736
5742
|
\`\`\`
|
|
5743
|
+
|
|
5744
|
+
\`\`\`book
|
|
5745
|
+
My Standalone Agent
|
|
5746
|
+
|
|
5747
|
+
FROM @Null
|
|
5748
|
+
RULE Speak only in English.
|
|
5749
|
+
\`\`\`
|
|
5737
5750
|
`);
|
|
5738
5751
|
}
|
|
5739
5752
|
applyToAgentModelRequirements(requirements, content) {
|
|
@@ -30582,6 +30595,385 @@
|
|
|
30582
30595
|
return `${scriptPath}.test.sh`;
|
|
30583
30596
|
}
|
|
30584
30597
|
|
|
30598
|
+
/**
|
|
30599
|
+
* Lists the direct project directories of one agent folder.
|
|
30600
|
+
*
|
|
30601
|
+
* @param agentFolderPath - Absolute path of the local agent folder.
|
|
30602
|
+
* @returns Project directory names, or an empty list when the agent has no projects folder.
|
|
30603
|
+
*/
|
|
30604
|
+
async function listAgentProjectDirectoryNames(agentFolderPath) {
|
|
30605
|
+
try {
|
|
30606
|
+
const projectsRootEntries = await promises.readdir(path.join(agentFolderPath, AGENT_PROJECTS_DIRECTORY_PATH), {
|
|
30607
|
+
withFileTypes: true,
|
|
30608
|
+
});
|
|
30609
|
+
return projectsRootEntries
|
|
30610
|
+
.filter((projectsRootEntry) => projectsRootEntry.isDirectory())
|
|
30611
|
+
.map((projectDirectoryEntry) => projectDirectoryEntry.name);
|
|
30612
|
+
}
|
|
30613
|
+
catch (_a) {
|
|
30614
|
+
return [];
|
|
30615
|
+
}
|
|
30616
|
+
}
|
|
30617
|
+
|
|
30618
|
+
/**
|
|
30619
|
+
* Largest git output kept in memory, so an enormous diff can never exhaust the runner process.
|
|
30620
|
+
*/
|
|
30621
|
+
const AGENT_PROJECT_GIT_OUTPUT_MAX_BYTES = 8 * 1024 * 1024;
|
|
30622
|
+
/**
|
|
30623
|
+
* Time after which one git command of a project repository is given up on.
|
|
30624
|
+
*/
|
|
30625
|
+
const AGENT_PROJECT_GIT_TIMEOUT_MS = 60 * 1000;
|
|
30626
|
+
/**
|
|
30627
|
+
* Author and committer used for project commits when no coding-agent identity is configured.
|
|
30628
|
+
*
|
|
30629
|
+
* A project repository is created by the runner on a server which usually has no git identity at
|
|
30630
|
+
* all, so committing must never depend on the machine configuration.
|
|
30631
|
+
*/
|
|
30632
|
+
const AGENT_PROJECT_GIT_FALLBACK_IDENTITY = {
|
|
30633
|
+
GIT_AUTHOR_NAME: 'Promptbook Agent',
|
|
30634
|
+
GIT_AUTHOR_EMAIL: 'agent@promptbook.studio',
|
|
30635
|
+
GIT_COMMITTER_NAME: 'Promptbook Agent',
|
|
30636
|
+
GIT_COMMITTER_EMAIL: 'agent@promptbook.studio',
|
|
30637
|
+
};
|
|
30638
|
+
/**
|
|
30639
|
+
* Runs one git command inside one agent project directory.
|
|
30640
|
+
*
|
|
30641
|
+
* Commands are executed without a shell and with an explicit argument list, so a project name or
|
|
30642
|
+
* a file path can never be interpreted as a shell fragment. A failing command is reported through
|
|
30643
|
+
* `isSuccessful` instead of throwing, because git uses the exit code to answer questions such as
|
|
30644
|
+
* "is there anything staged" and because auto-committing a project must never fail an answer the
|
|
30645
|
+
* agent already produced.
|
|
30646
|
+
*
|
|
30647
|
+
* @param options - Project directory and the git arguments to run there.
|
|
30648
|
+
* @returns Outcome of the command.
|
|
30649
|
+
*/
|
|
30650
|
+
async function runAgentProjectGitCommand(options) {
|
|
30651
|
+
return await new Promise((resolve) => {
|
|
30652
|
+
child_process.execFile('git', [...options.args], {
|
|
30653
|
+
cwd: options.projectPath,
|
|
30654
|
+
env: { ...process.env, ...AGENT_PROJECT_GIT_FALLBACK_IDENTITY, ...(buildAgentGitEnv() || {}) },
|
|
30655
|
+
maxBuffer: AGENT_PROJECT_GIT_OUTPUT_MAX_BYTES,
|
|
30656
|
+
timeout: AGENT_PROJECT_GIT_TIMEOUT_MS,
|
|
30657
|
+
windowsHide: true,
|
|
30658
|
+
}, (error, stdout) => {
|
|
30659
|
+
resolve({
|
|
30660
|
+
isSuccessful: !error,
|
|
30661
|
+
output: stripTrailingNewline(stdout || ''),
|
|
30662
|
+
});
|
|
30663
|
+
});
|
|
30664
|
+
});
|
|
30665
|
+
}
|
|
30666
|
+
/**
|
|
30667
|
+
* Removes the single trailing newline git appends to its output.
|
|
30668
|
+
*
|
|
30669
|
+
* @param output - Raw command output.
|
|
30670
|
+
* @returns Output without its trailing newline.
|
|
30671
|
+
*
|
|
30672
|
+
* @private helper of `runAgentProjectGitCommand`
|
|
30673
|
+
*/
|
|
30674
|
+
function stripTrailingNewline(output) {
|
|
30675
|
+
return output.replace(/\r?\n$/u, '');
|
|
30676
|
+
}
|
|
30677
|
+
|
|
30678
|
+
/**
|
|
30679
|
+
* Branch created for a project repository, so every agent project starts with the same history.
|
|
30680
|
+
*/
|
|
30681
|
+
const AGENT_PROJECT_GIT_INITIAL_BRANCH = 'main';
|
|
30682
|
+
/**
|
|
30683
|
+
* Paths kept out of a project repository created by the runner.
|
|
30684
|
+
*
|
|
30685
|
+
* Only a project which brings no ignore rules of its own receives these, and they cover exactly
|
|
30686
|
+
* the two things that must never enter an automatic commit: installed dependencies and secrets.
|
|
30687
|
+
*/
|
|
30688
|
+
const AGENT_PROJECT_GIT_DEFAULT_IGNORE_PATHS = _spaceTrim.spaceTrim(`
|
|
30689
|
+
node_modules/
|
|
30690
|
+
.env
|
|
30691
|
+
.env.*
|
|
30692
|
+
`);
|
|
30693
|
+
/**
|
|
30694
|
+
* Makes sure one agent project is a git repository of its own.
|
|
30695
|
+
*
|
|
30696
|
+
* A project which is already tracked by a repository around the agent folder is deliberately left
|
|
30697
|
+
* alone: initializing a repository inside it would turn it into an embedded repository and break
|
|
30698
|
+
* the history that already covers it.
|
|
30699
|
+
*
|
|
30700
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30701
|
+
* @returns How the project relates to git after this call.
|
|
30702
|
+
*/
|
|
30703
|
+
async function ensureAgentProjectGitRepository(projectPath) {
|
|
30704
|
+
if (await isExistingDirectory$1(path.join(projectPath, '.git'))) {
|
|
30705
|
+
return 'own-repository';
|
|
30706
|
+
}
|
|
30707
|
+
if (await isProjectTrackedByOuterRepository(projectPath)) {
|
|
30708
|
+
return 'tracked-elsewhere';
|
|
30709
|
+
}
|
|
30710
|
+
if (!(await initializeAgentProjectGitRepository(projectPath))) {
|
|
30711
|
+
return 'unavailable';
|
|
30712
|
+
}
|
|
30713
|
+
await writeDefaultAgentProjectGitignoreIfMissing(projectPath);
|
|
30714
|
+
return 'own-repository';
|
|
30715
|
+
}
|
|
30716
|
+
/**
|
|
30717
|
+
* Creates the repository of one project, naming its first branch when git supports it.
|
|
30718
|
+
*
|
|
30719
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30720
|
+
* @returns `true` when the project is a repository afterwards.
|
|
30721
|
+
*
|
|
30722
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30723
|
+
*/
|
|
30724
|
+
async function initializeAgentProjectGitRepository(projectPath) {
|
|
30725
|
+
const initResult = await runAgentProjectGitCommand({
|
|
30726
|
+
projectPath,
|
|
30727
|
+
args: ['init', `--initial-branch=${AGENT_PROJECT_GIT_INITIAL_BRANCH}`],
|
|
30728
|
+
});
|
|
30729
|
+
if (initResult.isSuccessful) {
|
|
30730
|
+
return true;
|
|
30731
|
+
}
|
|
30732
|
+
// Note: `--initial-branch` needs git 2.28, so an older git still gets its repository
|
|
30733
|
+
return (await runAgentProjectGitCommand({ projectPath, args: ['init'] })).isSuccessful;
|
|
30734
|
+
}
|
|
30735
|
+
/**
|
|
30736
|
+
* Checks whether a repository around the agent folder already tracks the project files.
|
|
30737
|
+
*
|
|
30738
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30739
|
+
* @returns `true` when an outer repository tracks at least one file of the project.
|
|
30740
|
+
*
|
|
30741
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30742
|
+
*/
|
|
30743
|
+
async function isProjectTrackedByOuterRepository(projectPath) {
|
|
30744
|
+
const trackedFilesResult = await runAgentProjectGitCommand({
|
|
30745
|
+
projectPath,
|
|
30746
|
+
args: ['ls-files', '--', '.'],
|
|
30747
|
+
});
|
|
30748
|
+
return trackedFilesResult.isSuccessful && trackedFilesResult.output.trim().length > 0;
|
|
30749
|
+
}
|
|
30750
|
+
/**
|
|
30751
|
+
* Writes the default ignore rules into a freshly initialized project repository.
|
|
30752
|
+
*
|
|
30753
|
+
* A project which already brings its own rules keeps them untouched.
|
|
30754
|
+
*
|
|
30755
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30756
|
+
*
|
|
30757
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30758
|
+
*/
|
|
30759
|
+
async function writeDefaultAgentProjectGitignoreIfMissing(projectPath) {
|
|
30760
|
+
const gitignorePath = path.join(projectPath, '.gitignore');
|
|
30761
|
+
try {
|
|
30762
|
+
await promises.stat(gitignorePath);
|
|
30763
|
+
return;
|
|
30764
|
+
}
|
|
30765
|
+
catch (_a) {
|
|
30766
|
+
// Note: A project without ignore rules would commit its installed dependencies
|
|
30767
|
+
}
|
|
30768
|
+
await promises.writeFile(gitignorePath, `${AGENT_PROJECT_GIT_DEFAULT_IGNORE_PATHS}\n`, 'utf-8');
|
|
30769
|
+
}
|
|
30770
|
+
/**
|
|
30771
|
+
* Checks whether one path is an existing directory.
|
|
30772
|
+
*
|
|
30773
|
+
* @param directoryPath - Absolute path to check.
|
|
30774
|
+
* @returns `true` when the path exists and is a directory.
|
|
30775
|
+
*
|
|
30776
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30777
|
+
*/
|
|
30778
|
+
async function isExistingDirectory$1(directoryPath) {
|
|
30779
|
+
try {
|
|
30780
|
+
return (await promises.stat(directoryPath)).isDirectory();
|
|
30781
|
+
}
|
|
30782
|
+
catch (_a) {
|
|
30783
|
+
return false;
|
|
30784
|
+
}
|
|
30785
|
+
}
|
|
30786
|
+
|
|
30787
|
+
/**
|
|
30788
|
+
* Largest diff carried into a chat, so one huge commit cannot bloat every message payload.
|
|
30789
|
+
*/
|
|
30790
|
+
const AGENT_PROJECT_DIFF_MAX_LENGTH = 20000;
|
|
30791
|
+
/**
|
|
30792
|
+
* Describes the latest commit of one agent project repository.
|
|
30793
|
+
*
|
|
30794
|
+
* @param options - Project directory and the project name the description is reported under.
|
|
30795
|
+
* @returns Description of the commit, or `null` when git could not describe it.
|
|
30796
|
+
*/
|
|
30797
|
+
async function readAgentProjectCommitChange(options) {
|
|
30798
|
+
const { projectPath, projectName } = options;
|
|
30799
|
+
const [commitHashResult, committedAtResult, numstatResult, diffResult] = await Promise.all([
|
|
30800
|
+
runAgentProjectGitCommand({ projectPath, args: ['rev-parse', 'HEAD'] }),
|
|
30801
|
+
runAgentProjectGitCommand({ projectPath, args: ['show', '--no-patch', '--format=%cI', 'HEAD'] }),
|
|
30802
|
+
runAgentProjectGitCommand({ projectPath, args: ['show', '--numstat', '--format=', 'HEAD'] }),
|
|
30803
|
+
runAgentProjectGitCommand({ projectPath, args: ['show', '--patch', '--format=', 'HEAD'] }),
|
|
30804
|
+
]);
|
|
30805
|
+
if (!commitHashResult.isSuccessful || commitHashResult.output.trim().length === 0) {
|
|
30806
|
+
return null;
|
|
30807
|
+
}
|
|
30808
|
+
const changedFiles = parseAgentProjectNumstat(numstatResult.isSuccessful ? numstatResult.output : '');
|
|
30809
|
+
const diff = diffResult.isSuccessful ? diffResult.output : '';
|
|
30810
|
+
return {
|
|
30811
|
+
projectName,
|
|
30812
|
+
commitHash: commitHashResult.output.trim(),
|
|
30813
|
+
committedAt: resolveCommittedAt(committedAtResult.isSuccessful ? committedAtResult.output : ''),
|
|
30814
|
+
changedFiles,
|
|
30815
|
+
insertionCount: sumChangedFileCounts(changedFiles, 'insertionCount'),
|
|
30816
|
+
deletionCount: sumChangedFileCounts(changedFiles, 'deletionCount'),
|
|
30817
|
+
diff: diff.slice(0, AGENT_PROJECT_DIFF_MAX_LENGTH),
|
|
30818
|
+
isDiffTruncated: diff.length > AGENT_PROJECT_DIFF_MAX_LENGTH,
|
|
30819
|
+
};
|
|
30820
|
+
}
|
|
30821
|
+
/**
|
|
30822
|
+
* Parses the `git show --numstat` output into changed files.
|
|
30823
|
+
*
|
|
30824
|
+
* Binary files report `-` instead of line counts, which is kept as a zero-line change so the file
|
|
30825
|
+
* is still listed as touched.
|
|
30826
|
+
*
|
|
30827
|
+
* @param numstatOutput - Raw numstat output.
|
|
30828
|
+
* @returns Changed files in the order git reported them.
|
|
30829
|
+
*
|
|
30830
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30831
|
+
*/
|
|
30832
|
+
function parseAgentProjectNumstat(numstatOutput) {
|
|
30833
|
+
return numstatOutput
|
|
30834
|
+
.split(/\r?\n/u)
|
|
30835
|
+
.map((numstatLine) => numstatLine.split('\t'))
|
|
30836
|
+
.filter((numstatColumns) => numstatColumns.length >= 3 && numstatColumns[2].trim().length > 0)
|
|
30837
|
+
.map((numstatColumns) => ({
|
|
30838
|
+
path: numstatColumns.slice(2).join('\t').trim(),
|
|
30839
|
+
insertionCount: parseChangedLineCount(numstatColumns[0]),
|
|
30840
|
+
deletionCount: parseChangedLineCount(numstatColumns[1]),
|
|
30841
|
+
}));
|
|
30842
|
+
}
|
|
30843
|
+
/**
|
|
30844
|
+
* Parses one numstat line count.
|
|
30845
|
+
*
|
|
30846
|
+
* @param rawLineCount - Raw numstat column.
|
|
30847
|
+
* @returns Parsed count, or `0` for binary files and unparseable columns.
|
|
30848
|
+
*
|
|
30849
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30850
|
+
*/
|
|
30851
|
+
function parseChangedLineCount(rawLineCount) {
|
|
30852
|
+
const parsedLineCount = Number.parseInt(rawLineCount.trim(), 10);
|
|
30853
|
+
return Number.isFinite(parsedLineCount) && parsedLineCount >= 0 ? parsedLineCount : 0;
|
|
30854
|
+
}
|
|
30855
|
+
/**
|
|
30856
|
+
* Sums one line-count field across all changed files.
|
|
30857
|
+
*
|
|
30858
|
+
* @param changedFiles - Changed files of the commit.
|
|
30859
|
+
* @param countName - Field to sum.
|
|
30860
|
+
* @returns Total count.
|
|
30861
|
+
*
|
|
30862
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30863
|
+
*/
|
|
30864
|
+
function sumChangedFileCounts(changedFiles, countName) {
|
|
30865
|
+
return changedFiles.reduce((total, changedFile) => total + changedFile[countName], 0);
|
|
30866
|
+
}
|
|
30867
|
+
/**
|
|
30868
|
+
* Normalizes the commit timestamp git reported.
|
|
30869
|
+
*
|
|
30870
|
+
* @param rawCommittedAt - Raw ISO timestamp from git.
|
|
30871
|
+
* @returns Usable ISO timestamp, falling back to the current time when git reported none.
|
|
30872
|
+
*
|
|
30873
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30874
|
+
*/
|
|
30875
|
+
function resolveCommittedAt(rawCommittedAt) {
|
|
30876
|
+
const trimmedCommittedAt = rawCommittedAt.trim();
|
|
30877
|
+
if (trimmedCommittedAt.length === 0 || !Number.isFinite(Date.parse(trimmedCommittedAt))) {
|
|
30878
|
+
return new Date().toISOString();
|
|
30879
|
+
}
|
|
30880
|
+
return new Date(trimmedCommittedAt).toISOString();
|
|
30881
|
+
}
|
|
30882
|
+
|
|
30883
|
+
/**
|
|
30884
|
+
* Commits everything one answered message changed inside one agent project.
|
|
30885
|
+
*
|
|
30886
|
+
* The project is turned into a git repository first when it is not one yet, so the work of every
|
|
30887
|
+
* answer stays recoverable and reviewable as a normal commit history.
|
|
30888
|
+
*
|
|
30889
|
+
* @param options - Project identity and the commit message describing the answered message.
|
|
30890
|
+
* @returns What was committed, or `null` when the project changed nothing or cannot be committed.
|
|
30891
|
+
*/
|
|
30892
|
+
async function commitAgentProjectChanges(options) {
|
|
30893
|
+
const { projectPath, projectName, commitMessage } = options;
|
|
30894
|
+
if ((await ensureAgentProjectGitRepository(projectPath)) !== 'own-repository') {
|
|
30895
|
+
return null;
|
|
30896
|
+
}
|
|
30897
|
+
const stageResult = await runAgentProjectGitCommand({ projectPath, args: ['add', '--all', '--', '.'] });
|
|
30898
|
+
if (!stageResult.isSuccessful) {
|
|
30899
|
+
return null;
|
|
30900
|
+
}
|
|
30901
|
+
if (!(await hasStagedAgentProjectChanges(projectPath))) {
|
|
30902
|
+
return null;
|
|
30903
|
+
}
|
|
30904
|
+
const commitResult = await runAgentProjectGitCommand({
|
|
30905
|
+
projectPath,
|
|
30906
|
+
args: ['commit', '--message', commitMessage],
|
|
30907
|
+
});
|
|
30908
|
+
if (!commitResult.isSuccessful) {
|
|
30909
|
+
return null;
|
|
30910
|
+
}
|
|
30911
|
+
return await readAgentProjectCommitChange({ projectPath, projectName });
|
|
30912
|
+
}
|
|
30913
|
+
/**
|
|
30914
|
+
* Checks whether the project index holds anything to commit.
|
|
30915
|
+
*
|
|
30916
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30917
|
+
* @returns `true` when committing would create a non-empty commit.
|
|
30918
|
+
*
|
|
30919
|
+
* @private helper of `commitAgentProjectChanges`
|
|
30920
|
+
*/
|
|
30921
|
+
async function hasStagedAgentProjectChanges(projectPath) {
|
|
30922
|
+
// Note: `--quiet` makes git answer through its exit code — success means nothing is staged
|
|
30923
|
+
const stagedChangesResult = await runAgentProjectGitCommand({
|
|
30924
|
+
projectPath,
|
|
30925
|
+
args: ['diff', '--cached', '--quiet'],
|
|
30926
|
+
});
|
|
30927
|
+
return !stagedChangesResult.isSuccessful;
|
|
30928
|
+
}
|
|
30929
|
+
|
|
30930
|
+
/**
|
|
30931
|
+
* Commits what one answered message changed in every project of one agent.
|
|
30932
|
+
*
|
|
30933
|
+
* Every project of an agent is its own git repository, so each answer which modified one becomes a
|
|
30934
|
+
* commit there. The projects are committed one after another because they share the git executable
|
|
30935
|
+
* and because an agent works with a handful of projects at most.
|
|
30936
|
+
*
|
|
30937
|
+
* Committing is best-effort bookkeeping around an answer the agent already produced: a project
|
|
30938
|
+
* whose commit fails is reported to the console and skipped instead of failing the message.
|
|
30939
|
+
*
|
|
30940
|
+
* @param options - Agent folder and the commit message describing the answered message.
|
|
30941
|
+
* @returns What was committed, one entry per project the message really changed.
|
|
30942
|
+
*/
|
|
30943
|
+
async function commitAnsweredMessageProjectChanges(options) {
|
|
30944
|
+
const { agentFolderPath, commitMessage } = options;
|
|
30945
|
+
const projectNames = await listAgentProjectDirectoryNames(agentFolderPath);
|
|
30946
|
+
const projectChanges = [];
|
|
30947
|
+
for (const projectName of projectNames) {
|
|
30948
|
+
const projectChange = await commitAgentProjectChangesSafely({
|
|
30949
|
+
projectPath: path.join(agentFolderPath, AGENT_PROJECTS_DIRECTORY_PATH, projectName),
|
|
30950
|
+
projectName,
|
|
30951
|
+
commitMessage,
|
|
30952
|
+
});
|
|
30953
|
+
if (projectChange) {
|
|
30954
|
+
projectChanges.push(projectChange);
|
|
30955
|
+
}
|
|
30956
|
+
}
|
|
30957
|
+
return projectChanges;
|
|
30958
|
+
}
|
|
30959
|
+
/**
|
|
30960
|
+
* Commits one project without letting its failure reach the answered message.
|
|
30961
|
+
*
|
|
30962
|
+
* @param options - Project identity and commit message.
|
|
30963
|
+
* @returns What was committed, or `null` when nothing changed or committing failed.
|
|
30964
|
+
*
|
|
30965
|
+
* @private helper of `commitAnsweredMessageProjectChanges`
|
|
30966
|
+
*/
|
|
30967
|
+
async function commitAgentProjectChangesSafely(options) {
|
|
30968
|
+
try {
|
|
30969
|
+
return await commitAgentProjectChanges(options);
|
|
30970
|
+
}
|
|
30971
|
+
catch (error) {
|
|
30972
|
+
console.warn(colors__default["default"].yellow(`Could not commit changes of project "${options.projectName}"`), error);
|
|
30973
|
+
return null;
|
|
30974
|
+
}
|
|
30975
|
+
}
|
|
30976
|
+
|
|
30585
30977
|
/**
|
|
30586
30978
|
* Checks whether one repository-relative path is tracked by Git.
|
|
30587
30979
|
*/
|
|
@@ -30627,7 +31019,7 @@
|
|
|
30627
31019
|
|
|
30628
31020
|
- You have 100% control over every project folder: create, read, modify, and delete files there, run scripts and commands inside it, and keep any persistent data you need between conversations.
|
|
30629
31021
|
- When the user asks you to build something (for example a website) or to do longer-term work, create a new project folder \`${AGENT_PROJECTS_DIRECTORY_PATH}/<project-name>/\` (use a short kebab-case name) and do the work inside it. Modify an existing project when the user refers to work you already did.
|
|
30630
|
-
-
|
|
31022
|
+
- Every project is a git repository and everything you change in one is committed there automatically once you finish the message, so you never need to run \`git init\` or \`git commit\` yourself and your work stays recoverable.
|
|
30631
31023
|
- Do not touch anything outside the \`${AGENT_PROJECTS_DIRECTORY_PATH}/\` directory beyond the file changes allowed at the top of this prompt.
|
|
30632
31024
|
|
|
30633
31025
|
${block(buildProjectReferenceInstructions(projectsUrlPath))}
|
|
@@ -30759,13 +31151,79 @@
|
|
|
30759
31151
|
}
|
|
30760
31152
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
30761
31153
|
|
|
31154
|
+
/**
|
|
31155
|
+
* Describes one planned-message schedule in a single sentence fragment.
|
|
31156
|
+
*
|
|
31157
|
+
* A planned message can repeat forever, repeat a bounded number of times, run inside a date window, or
|
|
31158
|
+
* wake the agent only once. Every surface showing a planned message — the wake-up itself, the goal-chat
|
|
31159
|
+
* notes, the planned-message prompt section, and the model tools — describes it with this one helper,
|
|
31160
|
+
* so an agent never has to reconcile two different wordings of the same plan.
|
|
31161
|
+
*
|
|
31162
|
+
* @param schedule - Schedule of the planned message.
|
|
31163
|
+
* @returns Fragment such as `repeats every 5 minutes (2 of 10 runs done)`.
|
|
31164
|
+
*
|
|
31165
|
+
* @private internal utility of the Agents Server planned messages
|
|
31166
|
+
*/
|
|
31167
|
+
function describeAgentPlannedMessageSchedule(schedule) {
|
|
31168
|
+
const scheduleParts = [
|
|
31169
|
+
describeAgentPlannedMessageRecurrence(schedule),
|
|
31170
|
+
...describeAgentPlannedMessageBounds(schedule),
|
|
31171
|
+
];
|
|
31172
|
+
return scheduleParts.join(', ');
|
|
31173
|
+
}
|
|
31174
|
+
/**
|
|
31175
|
+
* Describes how often one planned message wakes the agent.
|
|
31176
|
+
*
|
|
31177
|
+
* @param schedule - Schedule of the planned message.
|
|
31178
|
+
* @returns Recurrence fragment.
|
|
31179
|
+
*
|
|
31180
|
+
* @private internal utility of `describeAgentPlannedMessageSchedule`
|
|
31181
|
+
*/
|
|
31182
|
+
function describeAgentPlannedMessageRecurrence(schedule) {
|
|
31183
|
+
if (schedule.cronExpression) {
|
|
31184
|
+
return `repeats on cron \`${schedule.cronExpression}\``;
|
|
31185
|
+
}
|
|
31186
|
+
if (schedule.intervalMs) {
|
|
31187
|
+
return `repeats every ${formatTimeoutDurationHuman(schedule.intervalMs)}`;
|
|
31188
|
+
}
|
|
31189
|
+
return schedule.dueAt ? `wakes you once at ${schedule.dueAt}` : 'wakes you once';
|
|
31190
|
+
}
|
|
31191
|
+
/**
|
|
31192
|
+
* Describes the bounds limiting how long one planned message keeps repeating.
|
|
31193
|
+
*
|
|
31194
|
+
* @param schedule - Schedule of the planned message.
|
|
31195
|
+
* @returns Fragments for the starting date, ending date, and run count that are really set.
|
|
31196
|
+
*
|
|
31197
|
+
* @private internal utility of `describeAgentPlannedMessageSchedule`
|
|
31198
|
+
*/
|
|
31199
|
+
function describeAgentPlannedMessageBounds(schedule) {
|
|
31200
|
+
const bounds = [];
|
|
31201
|
+
const runCount = schedule.runCount || 0;
|
|
31202
|
+
if (schedule.startsAt) {
|
|
31203
|
+
bounds.push(`starting ${schedule.startsAt}`);
|
|
31204
|
+
}
|
|
31205
|
+
if (schedule.endsAt) {
|
|
31206
|
+
bounds.push(`until ${schedule.endsAt}`);
|
|
31207
|
+
}
|
|
31208
|
+
if (schedule.maxRunCount) {
|
|
31209
|
+
bounds.push(`${runCount} of ${schedule.maxRunCount} runs done`);
|
|
31210
|
+
}
|
|
31211
|
+
else if (runCount > 0) {
|
|
31212
|
+
bounds.push(`${runCount} run${runCount === 1 ? '' : 's'} done`);
|
|
31213
|
+
}
|
|
31214
|
+
if ((schedule.cronExpression || schedule.intervalMs) && schedule.dueAt) {
|
|
31215
|
+
bounds.push(`next at ${schedule.dueAt}`);
|
|
31216
|
+
}
|
|
31217
|
+
return bounds;
|
|
31218
|
+
}
|
|
31219
|
+
|
|
30762
31220
|
/**
|
|
30763
31221
|
* Builds the planned-message instructions available to an Agents Server-managed coding agent.
|
|
30764
31222
|
*
|
|
30765
31223
|
* Planned messages always target the agent's singleton goal chat, regardless of the chat in which the
|
|
30766
|
-
* wake-up is planned, and
|
|
30767
|
-
* the only channel that changes them, so an answer that merely claims a follow-up
|
|
30768
|
-
* nothing — and an answer that changes nothing keeps the current plan running.
|
|
31224
|
+
* wake-up is planned, and each of them keeps repeating until its schedule is over or it is cancelled.
|
|
31225
|
+
* The sidecar file is the only channel that changes them, so an answer that merely claims a follow-up
|
|
31226
|
+
* was planned changes nothing — and an answer that changes nothing keeps the current plan running.
|
|
30769
31227
|
*
|
|
30770
31228
|
* @param sidecar - Sidecar prepared by the Agents Server for the answered message.
|
|
30771
31229
|
* @returns Prompt section, or an empty string outside Agents Server-managed runs.
|
|
@@ -30777,19 +31235,25 @@
|
|
|
30777
31235
|
return _spaceTrim.spaceTrim((block) => `
|
|
30778
31236
|
## Planned goal-chat messages
|
|
30779
31237
|
|
|
30780
|
-
You can plan a message that
|
|
31238
|
+
You can plan a message that wakes you in your singleton goal chat. A planned message works like \`setInterval\`, not like \`setTimeout\`: once planned, it keeps waking you until its schedule is over or you cancel it. This works during every Agents Server-managed chat invocation, not only while answering inside the goal chat.
|
|
30781
31239
|
|
|
30782
31240
|
${block(buildCurrentPlannedMessagesLines(sidecar.currentPlannedMessages))}
|
|
30783
31241
|
|
|
30784
31242
|
Editing \`${sidecar.relativeSidecarPath}\` is the **only** way to change what wakes you. Writing in your answer that you scheduled something does not schedule anything.
|
|
30785
31243
|
|
|
30786
|
-
- **Keeping your planned messages as they are is the default.** When the list above already matches your goal, leave \`commands\` empty — every listed message keeps
|
|
30787
|
-
- When your goal needs a
|
|
30788
|
-
-
|
|
30789
|
-
|
|
31244
|
+
- **Keeping your planned messages as they are is the default.** When the list above already matches your goal, leave \`commands\` empty — every listed message keeps waking you on its own, and re-planning it would only duplicate it.
|
|
31245
|
+
- When your goal needs a wake-up that is not listed above, append \`{"action":"set","milliseconds":<repeat interval>,"message":"<what each future invocation must do>"}\` to the \`commands\` array of that file.
|
|
31246
|
+
- A planned message is shaped by these fields, which \`set\` and \`update\` both accept:
|
|
31247
|
+
- \`milliseconds\` — repeat interval of at least \`60000\`, or
|
|
31248
|
+
- \`cronExpression\` — a five-field cron such as \`"0 9 * * 1-5"\`, evaluated in the server time zone (use **either** this **or** \`milliseconds\`),
|
|
31249
|
+
- \`maxRunCount\` — how many times in total the message wakes you, for example \`1\` for a one-off message,
|
|
31250
|
+
- \`startsAt\` and \`endsAt\` — ISO dates bounding when it may wake you, for example \`"2026-09-01T08:00:00.000Z"\`.
|
|
31251
|
+
- When a listed message no longer matches your goal, append \`{"action":"update","timeoutId":"<timeout id>","<field>":<new value>}\` with only the fields you want to change. The message keeps its id, a field you leave out stays as it is, and \`null\` removes a bound such as \`endsAt\`. Use \`update\` instead of cancelling and planning the same message again.
|
|
31252
|
+
- When your goal no longer needs a listed message at all, append \`{"action":"cancel","timeoutId":"<timeout id>"}\` without planning a replacement.
|
|
30790
31253
|
- Never edit \`version\`, \`agentPermanentId\`, or \`currentPlannedMessages\`.
|
|
30791
|
-
- The Agents Server applies every command once your answer is finished, and each
|
|
30792
|
-
-
|
|
31254
|
+
- The Agents Server applies every command once your answer is finished, and each wake-up appears in the goal chat and invokes you there.
|
|
31255
|
+
- A planned message which finished — because it ran \`maxRunCount\` times or passed its \`endsAt\` — stops on its own and disappears from the list above, so you never have to clean it up.
|
|
31256
|
+
- Only mention a planned follow-up in your answer when it is really planned: either you appended the matching \`set\` or \`update\` command, or you kept one of the messages listed above.
|
|
30793
31257
|
`);
|
|
30794
31258
|
}
|
|
30795
31259
|
/**
|
|
@@ -30822,10 +31286,7 @@
|
|
|
30822
31286
|
function createCurrentPlannedMessageLine(plannedMessage) {
|
|
30823
31287
|
var _a;
|
|
30824
31288
|
const message = ((_a = plannedMessage.message) === null || _a === void 0 ? void 0 : _a.trim()) || 'Continue working towards the current goal.';
|
|
30825
|
-
|
|
30826
|
-
? `repeats every ${formatTimeoutDurationHuman(plannedMessage.intervalMs)}`
|
|
30827
|
-
: `wakes you once at ${plannedMessage.dueAt}`;
|
|
30828
|
-
return `- \`${plannedMessage.timeoutId}\` ${schedule}: ${message}`;
|
|
31289
|
+
return `- \`${plannedMessage.timeoutId}\` ${describeAgentPlannedMessageSchedule(plannedMessage)}: ${message}`;
|
|
30829
31290
|
}
|
|
30830
31291
|
|
|
30831
31292
|
/**
|
|
@@ -37885,7 +38346,7 @@
|
|
|
37885
38346
|
*
|
|
37886
38347
|
* @private internal convention shared by the Agents Server and agent-folder runner
|
|
37887
38348
|
*/
|
|
37888
|
-
const AGENT_PLANNED_MESSAGE_COMMAND_ACTIONS = ['set', 'cancel'];
|
|
38349
|
+
const AGENT_PLANNED_MESSAGE_COMMAND_ACTIONS = ['set', 'update', 'cancel'];
|
|
37889
38350
|
/**
|
|
37890
38351
|
* Creates the relative planned-message sidecar path of one queued message.
|
|
37891
38352
|
*
|
|
@@ -37977,19 +38438,35 @@
|
|
|
37977
38438
|
* Normalizes the optional fields of one already planned message.
|
|
37978
38439
|
*
|
|
37979
38440
|
* @param snapshot - Planned-message entry with the required identity fields.
|
|
37980
|
-
* @returns Snapshot with a usable
|
|
38441
|
+
* @returns Snapshot with a usable schedule and message.
|
|
37981
38442
|
*
|
|
37982
38443
|
* @private internal utility of `parseAgentPlannedMessagesSidecar`
|
|
37983
38444
|
*/
|
|
37984
38445
|
function createNormalizedAgentPlannedMessageSnapshot(snapshot) {
|
|
37985
|
-
const intervalMs = Number(snapshot.intervalMs);
|
|
37986
38446
|
return {
|
|
37987
38447
|
timeoutId: snapshot.timeoutId,
|
|
37988
38448
|
dueAt: snapshot.dueAt,
|
|
37989
38449
|
message: typeof snapshot.message === 'string' ? snapshot.message : null,
|
|
37990
|
-
intervalMs:
|
|
38450
|
+
intervalMs: normalizeAgentPlannedMessagePositiveCount(snapshot.intervalMs),
|
|
38451
|
+
cronExpression: typeof snapshot.cronExpression === 'string' ? snapshot.cronExpression : null,
|
|
38452
|
+
startsAt: typeof snapshot.startsAt === 'string' ? snapshot.startsAt : null,
|
|
38453
|
+
endsAt: typeof snapshot.endsAt === 'string' ? snapshot.endsAt : null,
|
|
38454
|
+
maxRunCount: normalizeAgentPlannedMessagePositiveCount(snapshot.maxRunCount),
|
|
38455
|
+
runCount: normalizeAgentPlannedMessagePositiveCount(snapshot.runCount) || 0,
|
|
37991
38456
|
};
|
|
37992
38457
|
}
|
|
38458
|
+
/**
|
|
38459
|
+
* Normalizes one optional positive whole number of a planned-message snapshot.
|
|
38460
|
+
*
|
|
38461
|
+
* @param value - Untrusted interval, run count, or run-count limit.
|
|
38462
|
+
* @returns Whole positive number, or `null` when the value cannot be used.
|
|
38463
|
+
*
|
|
38464
|
+
* @private internal utility of `parseAgentPlannedMessagesSidecar`
|
|
38465
|
+
*/
|
|
38466
|
+
function normalizeAgentPlannedMessagePositiveCount(value) {
|
|
38467
|
+
const numericValue = Number(value);
|
|
38468
|
+
return Number.isFinite(numericValue) && numericValue > 0 ? Math.floor(numericValue) : null;
|
|
38469
|
+
}
|
|
37993
38470
|
/**
|
|
37994
38471
|
* Checks whether one untrusted sidecar entry describes an already planned message.
|
|
37995
38472
|
*
|
|
@@ -38215,6 +38692,286 @@
|
|
|
38215
38692
|
}
|
|
38216
38693
|
}
|
|
38217
38694
|
|
|
38695
|
+
/**
|
|
38696
|
+
* Maximum count of external sources reported for one answered message.
|
|
38697
|
+
*
|
|
38698
|
+
* A single answer can reach the same kind of source many times, so the chip row below it stays
|
|
38699
|
+
* readable by keeping only the sources touched first.
|
|
38700
|
+
*
|
|
38701
|
+
* @private internal constant of agent-message touched external sources
|
|
38702
|
+
*/
|
|
38703
|
+
const MAX_TOUCHED_EXTERNAL_SOURCES = 12;
|
|
38704
|
+
/**
|
|
38705
|
+
* Maximum length of one search query shown as the name of a touched search source.
|
|
38706
|
+
*
|
|
38707
|
+
* @private internal constant of agent-message touched external sources
|
|
38708
|
+
*/
|
|
38709
|
+
const MAX_SEARCH_QUERY_LENGTH = 48;
|
|
38710
|
+
/**
|
|
38711
|
+
* Separator between the segments of one integration tool name, as in `mcp__gmail__create_draft`.
|
|
38712
|
+
*
|
|
38713
|
+
* @private internal constant of agent-message touched external sources
|
|
38714
|
+
*/
|
|
38715
|
+
const INTEGRATION_TOOL_NAME_SEPARATOR = '__';
|
|
38716
|
+
/**
|
|
38717
|
+
* First segment marking one tool name as belonging to an integration.
|
|
38718
|
+
*
|
|
38719
|
+
* @private internal constant of agent-message touched external sources
|
|
38720
|
+
*/
|
|
38721
|
+
const INTEGRATION_TOOL_NAME_PREFIX = 'mcp';
|
|
38722
|
+
/**
|
|
38723
|
+
* Names of the harness tools which look something up on the web, indexed for case-insensitive matching.
|
|
38724
|
+
*
|
|
38725
|
+
* @private internal constant of agent-message touched external sources
|
|
38726
|
+
*/
|
|
38727
|
+
const WEB_SEARCH_TOOL_NAMES = new Set(['WebSearch', 'web_search'].map((webSearchToolName) => webSearchToolName.toLowerCase()));
|
|
38728
|
+
/**
|
|
38729
|
+
* Matches one shell command invoking a network client, whose arguments therefore address the outside world.
|
|
38730
|
+
*
|
|
38731
|
+
* @private internal constant of agent-message touched external sources
|
|
38732
|
+
*/
|
|
38733
|
+
const NETWORK_CLIENT_COMMAND_REGEX = /(^|[\s|;&(])(curl|wget|invoke-webrequest|iwr)\b/iu;
|
|
38734
|
+
/**
|
|
38735
|
+
* Matches one web address inside a shell command.
|
|
38736
|
+
*
|
|
38737
|
+
* @private internal constant of agent-message touched external sources
|
|
38738
|
+
*/
|
|
38739
|
+
const COMMAND_URL_REGEX = /https?:\/\/[^\s"'`<>)\]]+/giu;
|
|
38740
|
+
/**
|
|
38741
|
+
* Separators used between the words of one integration name.
|
|
38742
|
+
*
|
|
38743
|
+
* @private internal constant of agent-message touched external sources
|
|
38744
|
+
*/
|
|
38745
|
+
const INTEGRATION_NAME_WORD_SEPARATOR_REGEX = /[-_.\s]+/gu;
|
|
38746
|
+
/**
|
|
38747
|
+
* Hostnames which address the machine the agent runs on and are therefore not external.
|
|
38748
|
+
*
|
|
38749
|
+
* @private internal constant of agent-message touched external sources
|
|
38750
|
+
*/
|
|
38751
|
+
const LOCAL_HOSTNAMES = new Set(['localhost', '127.0.0.1', '0.0.0.0', '::1', '[::1]']);
|
|
38752
|
+
/**
|
|
38753
|
+
* Resolves which sources outside the agent one coding harness touched while answering a single message.
|
|
38754
|
+
*
|
|
38755
|
+
* The runtime log streams what the harness really did, so a source counts as touched when the
|
|
38756
|
+
* harness reached it in a tool invocation — calling an integration, fetching a web address,
|
|
38757
|
+
* searching the web, or running a network client in the shell. Only tool payloads are inspected:
|
|
38758
|
+
* tool results and assistant narration are ignored so a service merely mentioned in the
|
|
38759
|
+
* conversation is never reported, and addresses of the machine the agent runs on are dropped
|
|
38760
|
+
* because they are internal.
|
|
38761
|
+
*
|
|
38762
|
+
* @param options - Raw runtime log content of one answered message.
|
|
38763
|
+
* @returns Touched external sources without duplicates, ordered by first appearance.
|
|
38764
|
+
* @private internal utility of the agent-message runtime
|
|
38765
|
+
*/
|
|
38766
|
+
function resolveAgentMessageTouchedExternalSources(options) {
|
|
38767
|
+
const touchedExternalSources = new Map();
|
|
38768
|
+
for (const event of parseAgentMessageRuntimeLogEvents(options.logText)) {
|
|
38769
|
+
for (const externalSource of resolveRuntimeLogEventExternalSources(event)) {
|
|
38770
|
+
const externalSourceKey = createExternalSourceKey(externalSource);
|
|
38771
|
+
if (!touchedExternalSources.has(externalSourceKey)) {
|
|
38772
|
+
touchedExternalSources.set(externalSourceKey, externalSource);
|
|
38773
|
+
}
|
|
38774
|
+
if (touchedExternalSources.size === MAX_TOUCHED_EXTERNAL_SOURCES) {
|
|
38775
|
+
return Array.from(touchedExternalSources.values());
|
|
38776
|
+
}
|
|
38777
|
+
}
|
|
38778
|
+
}
|
|
38779
|
+
return Array.from(touchedExternalSources.values());
|
|
38780
|
+
}
|
|
38781
|
+
/**
|
|
38782
|
+
* Collects every external source described by one runtime log event.
|
|
38783
|
+
*
|
|
38784
|
+
* Claude Code reports tool invocations as `tool_use` content blocks, while Codex reports executed
|
|
38785
|
+
* commands, web searches, and integration calls as items.
|
|
38786
|
+
*
|
|
38787
|
+
* @param event - One structured runtime log event.
|
|
38788
|
+
* @returns External sources the event reached, possibly with duplicates.
|
|
38789
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38790
|
+
*/
|
|
38791
|
+
function resolveRuntimeLogEventExternalSources(event) {
|
|
38792
|
+
var _a;
|
|
38793
|
+
const externalSources = [];
|
|
38794
|
+
for (const contentBlock of ((_a = event.message) === null || _a === void 0 ? void 0 : _a.content) || []) {
|
|
38795
|
+
if (contentBlock.type === 'tool_use') {
|
|
38796
|
+
externalSources.push(...resolveToolUseExternalSources(contentBlock));
|
|
38797
|
+
}
|
|
38798
|
+
}
|
|
38799
|
+
externalSources.push(...resolveCodexItemExternalSources(event.item));
|
|
38800
|
+
return externalSources;
|
|
38801
|
+
}
|
|
38802
|
+
/**
|
|
38803
|
+
* Collects the external sources reached by one Claude Code tool invocation.
|
|
38804
|
+
*
|
|
38805
|
+
* @param contentBlock - One `tool_use` content block.
|
|
38806
|
+
* @returns External sources the invocation reached.
|
|
38807
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38808
|
+
*/
|
|
38809
|
+
function resolveToolUseExternalSources(contentBlock) {
|
|
38810
|
+
const toolName = contentBlock.name || '';
|
|
38811
|
+
const toolInput = contentBlock.input || {};
|
|
38812
|
+
return collectDefinedExternalSources([
|
|
38813
|
+
createIntegrationExternalSource(resolveIntegrationName(toolName)),
|
|
38814
|
+
typeof toolInput.url === 'string' ? createWebsiteExternalSource(toolInput.url) : null,
|
|
38815
|
+
WEB_SEARCH_TOOL_NAMES.has(toolName.toLowerCase()) && typeof toolInput.query === 'string'
|
|
38816
|
+
? createSearchExternalSource(toolInput.query)
|
|
38817
|
+
: null,
|
|
38818
|
+
...(typeof toolInput.command === 'string' ? resolveNetworkCommandExternalSources(toolInput.command) : []),
|
|
38819
|
+
]);
|
|
38820
|
+
}
|
|
38821
|
+
/**
|
|
38822
|
+
* Collects the external sources reached by one Codex runtime item.
|
|
38823
|
+
*
|
|
38824
|
+
* @param item - One Codex item of a runtime log event.
|
|
38825
|
+
* @returns External sources the item reached.
|
|
38826
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38827
|
+
*/
|
|
38828
|
+
function resolveCodexItemExternalSources(item) {
|
|
38829
|
+
if (!item) {
|
|
38830
|
+
return [];
|
|
38831
|
+
}
|
|
38832
|
+
return collectDefinedExternalSources([
|
|
38833
|
+
item.type === 'mcp_tool_call'
|
|
38834
|
+
? createIntegrationExternalSource(item.server || resolveIntegrationName(item.tool || ''))
|
|
38835
|
+
: null,
|
|
38836
|
+
item.type === 'web_search' && typeof item.query === 'string' ? createSearchExternalSource(item.query) : null,
|
|
38837
|
+
...(typeof item.command === 'string' ? resolveNetworkCommandExternalSources(item.command) : []),
|
|
38838
|
+
]);
|
|
38839
|
+
}
|
|
38840
|
+
/**
|
|
38841
|
+
* Drops the candidates which turned out not to describe an external source.
|
|
38842
|
+
*
|
|
38843
|
+
* @param candidates - Resolved sources mixed with the candidates that resolved to nothing.
|
|
38844
|
+
* @returns Only the sources which were resolved.
|
|
38845
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38846
|
+
*/
|
|
38847
|
+
function collectDefinedExternalSources(candidates) {
|
|
38848
|
+
return candidates.filter((candidate) => candidate !== null);
|
|
38849
|
+
}
|
|
38850
|
+
/**
|
|
38851
|
+
* Resolves the integration a tool name belongs to, following the `mcp__<integration>__<tool>` convention.
|
|
38852
|
+
*
|
|
38853
|
+
* @param toolName - Raw harness tool name.
|
|
38854
|
+
* @returns Raw integration name, or `null` when the tool belongs to no integration.
|
|
38855
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38856
|
+
*/
|
|
38857
|
+
function resolveIntegrationName(toolName) {
|
|
38858
|
+
const toolNameSegments = toolName.split(INTEGRATION_TOOL_NAME_SEPARATOR);
|
|
38859
|
+
if (toolNameSegments.length < 3 || toolNameSegments[0].toLowerCase() !== INTEGRATION_TOOL_NAME_PREFIX) {
|
|
38860
|
+
return null;
|
|
38861
|
+
}
|
|
38862
|
+
return toolNameSegments[1] || null;
|
|
38863
|
+
}
|
|
38864
|
+
/**
|
|
38865
|
+
* Creates one touched integration source.
|
|
38866
|
+
*
|
|
38867
|
+
* @param integrationName - Raw integration name, or `null` when there is none.
|
|
38868
|
+
* @returns Touched source, or `null` when the integration cannot be named.
|
|
38869
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38870
|
+
*/
|
|
38871
|
+
function createIntegrationExternalSource(integrationName) {
|
|
38872
|
+
const humanizedIntegrationName = humanizeIntegrationName(integrationName || '');
|
|
38873
|
+
if (humanizedIntegrationName === '') {
|
|
38874
|
+
return null;
|
|
38875
|
+
}
|
|
38876
|
+
return { kind: 'integration', name: humanizedIntegrationName };
|
|
38877
|
+
}
|
|
38878
|
+
/**
|
|
38879
|
+
* Creates one touched website source.
|
|
38880
|
+
*
|
|
38881
|
+
* @param rawUrl - Raw web address the harness reached.
|
|
38882
|
+
* @returns Touched source, or `null` when the address is unusable or addresses the local machine.
|
|
38883
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38884
|
+
*/
|
|
38885
|
+
function createWebsiteExternalSource(rawUrl) {
|
|
38886
|
+
let url;
|
|
38887
|
+
try {
|
|
38888
|
+
url = new URL(rawUrl.trim());
|
|
38889
|
+
}
|
|
38890
|
+
catch (_a) {
|
|
38891
|
+
return null;
|
|
38892
|
+
}
|
|
38893
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
38894
|
+
return null;
|
|
38895
|
+
}
|
|
38896
|
+
const hostname = url.hostname.toLowerCase();
|
|
38897
|
+
if (hostname === '' || LOCAL_HOSTNAMES.has(hostname) || hostname.endsWith('.localhost')) {
|
|
38898
|
+
return null;
|
|
38899
|
+
}
|
|
38900
|
+
return { kind: 'website', name: hostname, url: url.href };
|
|
38901
|
+
}
|
|
38902
|
+
/**
|
|
38903
|
+
* Creates one touched web search source.
|
|
38904
|
+
*
|
|
38905
|
+
* @param query - Raw query the harness looked up.
|
|
38906
|
+
* @returns Touched source, or `null` when the query is empty.
|
|
38907
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38908
|
+
*/
|
|
38909
|
+
function createSearchExternalSource(query) {
|
|
38910
|
+
const normalizedQuery = query.replace(/\s+/gu, ' ').trim();
|
|
38911
|
+
if (normalizedQuery === '') {
|
|
38912
|
+
return null;
|
|
38913
|
+
}
|
|
38914
|
+
return {
|
|
38915
|
+
kind: 'search',
|
|
38916
|
+
name: normalizedQuery.length <= MAX_SEARCH_QUERY_LENGTH
|
|
38917
|
+
? normalizedQuery
|
|
38918
|
+
: `${normalizedQuery.slice(0, MAX_SEARCH_QUERY_LENGTH).trimEnd()}…`,
|
|
38919
|
+
};
|
|
38920
|
+
}
|
|
38921
|
+
/**
|
|
38922
|
+
* Collects the websites addressed by one shell command running a network client.
|
|
38923
|
+
*
|
|
38924
|
+
* Commands which do not invoke a network client are ignored, so a web address that merely appears
|
|
38925
|
+
* in the text the agent writes into a file is never reported as touched.
|
|
38926
|
+
*
|
|
38927
|
+
* @param command - One executed shell command.
|
|
38928
|
+
* @returns Touched website sources of the command.
|
|
38929
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38930
|
+
*/
|
|
38931
|
+
function resolveNetworkCommandExternalSources(command) {
|
|
38932
|
+
if (!NETWORK_CLIENT_COMMAND_REGEX.test(command)) {
|
|
38933
|
+
return [];
|
|
38934
|
+
}
|
|
38935
|
+
const commandUrlRegex = new RegExp(COMMAND_URL_REGEX.source, COMMAND_URL_REGEX.flags);
|
|
38936
|
+
const externalSources = [];
|
|
38937
|
+
let commandUrlMatch = commandUrlRegex.exec(command);
|
|
38938
|
+
while (commandUrlMatch !== null) {
|
|
38939
|
+
const externalSource = createWebsiteExternalSource(commandUrlMatch[0]);
|
|
38940
|
+
if (externalSource) {
|
|
38941
|
+
externalSources.push(externalSource);
|
|
38942
|
+
}
|
|
38943
|
+
commandUrlMatch = commandUrlRegex.exec(command);
|
|
38944
|
+
}
|
|
38945
|
+
return externalSources;
|
|
38946
|
+
}
|
|
38947
|
+
/**
|
|
38948
|
+
* Converts one raw integration name into its user-facing form.
|
|
38949
|
+
*
|
|
38950
|
+
* For example `google-calendar` becomes `Google Calendar`.
|
|
38951
|
+
*
|
|
38952
|
+
* @param integrationName - Raw integration name.
|
|
38953
|
+
* @returns Human-readable integration name, or an empty string when there is nothing to show.
|
|
38954
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38955
|
+
*/
|
|
38956
|
+
function humanizeIntegrationName(integrationName) {
|
|
38957
|
+
return integrationName
|
|
38958
|
+
.trim()
|
|
38959
|
+
.split(INTEGRATION_NAME_WORD_SEPARATOR_REGEX)
|
|
38960
|
+
.filter((integrationNameWord) => integrationNameWord !== '')
|
|
38961
|
+
.map((integrationNameWord) => capitalize(integrationNameWord))
|
|
38962
|
+
.join(' ');
|
|
38963
|
+
}
|
|
38964
|
+
/**
|
|
38965
|
+
* Builds the key identifying one external source across the whole run.
|
|
38966
|
+
*
|
|
38967
|
+
* @param externalSource - One touched external source.
|
|
38968
|
+
* @returns Key under which repeated touches of the same source collapse into one.
|
|
38969
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38970
|
+
*/
|
|
38971
|
+
function createExternalSourceKey(externalSource) {
|
|
38972
|
+
return `${externalSource.kind}:${externalSource.name.toLowerCase()}`;
|
|
38973
|
+
}
|
|
38974
|
+
|
|
38218
38975
|
/**
|
|
38219
38976
|
* Matches one project directory name following the agent `projects/` folder in a file path or command.
|
|
38220
38977
|
*
|
|
@@ -38339,43 +39096,25 @@
|
|
|
38339
39096
|
}
|
|
38340
39097
|
|
|
38341
39098
|
/**
|
|
38342
|
-
* Resolves which agent projects one answered message
|
|
39099
|
+
* Resolves which agent projects and which external sources one answered message touched.
|
|
38343
39100
|
*
|
|
38344
39101
|
* The runtime log is deleted as soon as the harness run finishes, so this must be called while
|
|
38345
|
-
* the log still exists — the Agents Server later shows
|
|
38346
|
-
* answer. Reporting
|
|
38347
|
-
*
|
|
39102
|
+
* the log still exists — the Agents Server later shows everything reported here as chips below
|
|
39103
|
+
* the answer. Reporting touches is best-effort telemetry: an unreadable log or projects folder
|
|
39104
|
+
* simply yields nothing instead of failing the already answered message.
|
|
38348
39105
|
*
|
|
38349
39106
|
* @param options - Agent folder path and the live runtime log path of the answered message.
|
|
38350
|
-
* @returns Touched
|
|
39107
|
+
* @returns Touched projects and external sources, ordered by first appearance in the run.
|
|
38351
39108
|
*/
|
|
38352
|
-
async function
|
|
39109
|
+
async function resolveAnsweredMessageTouches(options) {
|
|
38353
39110
|
const [logText, knownProjectNames] = await Promise.all([
|
|
38354
39111
|
readOptionalTextFile(options.runtimeLogPath),
|
|
38355
39112
|
listAgentProjectDirectoryNames(options.projectPath),
|
|
38356
39113
|
]);
|
|
38357
|
-
return
|
|
38358
|
-
|
|
38359
|
-
|
|
38360
|
-
|
|
38361
|
-
*
|
|
38362
|
-
* @param projectPath - Absolute path of the local agent folder.
|
|
38363
|
-
* @returns Project directory names, or an empty list when the agent has no projects folder.
|
|
38364
|
-
*
|
|
38365
|
-
* @private helper of `resolveTouchedAgentProjects`
|
|
38366
|
-
*/
|
|
38367
|
-
async function listAgentProjectDirectoryNames(projectPath) {
|
|
38368
|
-
try {
|
|
38369
|
-
const projectsRootEntries = await promises.readdir(path.join(projectPath, AGENT_PROJECTS_DIRECTORY_PATH), {
|
|
38370
|
-
withFileTypes: true,
|
|
38371
|
-
});
|
|
38372
|
-
return projectsRootEntries
|
|
38373
|
-
.filter((projectsRootEntry) => projectsRootEntry.isDirectory())
|
|
38374
|
-
.map((projectDirectoryEntry) => projectDirectoryEntry.name);
|
|
38375
|
-
}
|
|
38376
|
-
catch (_a) {
|
|
38377
|
-
return [];
|
|
38378
|
-
}
|
|
39114
|
+
return {
|
|
39115
|
+
touchedProjectNames: resolveAgentMessageTouchedProjectNames({ logText, knownProjectNames }),
|
|
39116
|
+
touchedExternalSources: resolveAgentMessageTouchedExternalSources({ logText }),
|
|
39117
|
+
};
|
|
38379
39118
|
}
|
|
38380
39119
|
/**
|
|
38381
39120
|
* Reads one text file and treats a missing runtime log as "nothing was recorded".
|
|
@@ -38383,7 +39122,7 @@
|
|
|
38383
39122
|
* @param filePath - Absolute path of the file to read.
|
|
38384
39123
|
* @returns File content, or `null` when it cannot be read.
|
|
38385
39124
|
*
|
|
38386
|
-
* @private helper of `
|
|
39125
|
+
* @private helper of `resolveAnsweredMessageTouches`
|
|
38387
39126
|
*/
|
|
38388
39127
|
async function readOptionalTextFile(filePath) {
|
|
38389
39128
|
try {
|
|
@@ -38700,7 +39439,7 @@
|
|
|
38700
39439
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
38701
39440
|
const executionStartedAt = new Date().toISOString();
|
|
38702
39441
|
let promptRunResult;
|
|
38703
|
-
let
|
|
39442
|
+
let answeredMessageTouches = { touchedProjectNames: [], touchedExternalSources: [] };
|
|
38704
39443
|
try {
|
|
38705
39444
|
try {
|
|
38706
39445
|
promptRunResult = await withPromptRuntimeLog(scriptPath, async (logPath) => {
|
|
@@ -38716,9 +39455,12 @@
|
|
|
38716
39455
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(attemptCount);
|
|
38717
39456
|
},
|
|
38718
39457
|
});
|
|
38719
|
-
// Note: The runtime log is deleted right after this handler, so
|
|
39458
|
+
// Note: The runtime log is deleted right after this handler, so everything this
|
|
38720
39459
|
// answer worked with must be resolved while the log still exists.
|
|
38721
|
-
|
|
39460
|
+
answeredMessageTouches = await resolveAnsweredMessageTouches({
|
|
39461
|
+
projectPath,
|
|
39462
|
+
runtimeLogPath: logPath,
|
|
39463
|
+
});
|
|
38722
39464
|
return runResult;
|
|
38723
39465
|
}, { preserveArtifactsOnSuccess: false });
|
|
38724
39466
|
}
|
|
@@ -38736,6 +39478,12 @@
|
|
|
38736
39478
|
}
|
|
38737
39479
|
const executionFinishedAt = new Date().toISOString();
|
|
38738
39480
|
await normalizeLineEndingsForAgentRound(projectPath, runOptions, roundChangedFilesSnapshot);
|
|
39481
|
+
// Note: Every agent project keeps its own git history, so what this message did to a project is
|
|
39482
|
+
// committed there before the answer becomes visible and travels with the run report.
|
|
39483
|
+
const projectChanges = await commitAnsweredMessageProjectChanges({
|
|
39484
|
+
agentFolderPath: projectPath,
|
|
39485
|
+
commitMessage: buildAgentMessageCommitMessage(queuedMessage),
|
|
39486
|
+
});
|
|
38739
39487
|
const finishedTeamWorkspace = await finalizeAgentTeamConversationWorkspace({
|
|
38740
39488
|
projectPath,
|
|
38741
39489
|
queuedMessage,
|
|
@@ -38757,7 +39505,13 @@
|
|
|
38757
39505
|
startedAt: executionStartedAt,
|
|
38758
39506
|
finishedAt: executionFinishedAt,
|
|
38759
39507
|
},
|
|
38760
|
-
...(touchedProjectNames.length === 0
|
|
39508
|
+
...(answeredMessageTouches.touchedProjectNames.length === 0
|
|
39509
|
+
? {}
|
|
39510
|
+
: { touchedProjectNames: answeredMessageTouches.touchedProjectNames }),
|
|
39511
|
+
...(answeredMessageTouches.touchedExternalSources.length === 0
|
|
39512
|
+
? {}
|
|
39513
|
+
: { touchedExternalSources: answeredMessageTouches.touchedExternalSources }),
|
|
39514
|
+
...(projectChanges.length === 0 ? {} : { projectChanges }),
|
|
38761
39515
|
},
|
|
38762
39516
|
});
|
|
38763
39517
|
await commitAnsweredMessageIfEnabled({
|
|
@@ -41773,7 +42527,9 @@
|
|
|
41773
42527
|
async function $checkHarnessInstallation(definition, isHarnessUpdateCheckEnabled = true) {
|
|
41774
42528
|
const [installedVersion, latestVersion] = await Promise.all([
|
|
41775
42529
|
$resolveInstalledHarnessVersion(definition),
|
|
41776
|
-
isHarnessUpdateCheckEnabled
|
|
42530
|
+
isHarnessUpdateCheckEnabled
|
|
42531
|
+
? $resolveLatestNpmPackageVersion(definition.npmPackageName)
|
|
42532
|
+
: Promise.resolve(null),
|
|
41777
42533
|
]);
|
|
41778
42534
|
return {
|
|
41779
42535
|
definition,
|
|
@@ -42457,6 +43213,52 @@
|
|
|
42457
43213
|
// Note: [🟡] Code for CLI command [init](src/cli/cli-commands/coder/init.ts) should never be published outside of `@promptbook/cli`
|
|
42458
43214
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
42459
43215
|
|
|
43216
|
+
/**
|
|
43217
|
+
* Default wait duration applied before retrying a prompt round after an error (10 minutes).
|
|
43218
|
+
*
|
|
43219
|
+
* @private internal constant of `ptbk coder` wait handling
|
|
43220
|
+
*/
|
|
43221
|
+
const DEFAULT_WAIT_AFTER_ERROR_MS$1 = 10 * 60 * 1000;
|
|
43222
|
+
/**
|
|
43223
|
+
* Parses an optional Commander duration string and returns the resolved milliseconds.
|
|
43224
|
+
*
|
|
43225
|
+
* Returns `defaultMs` when the flag was not provided or was provided without a non-empty value.
|
|
43226
|
+
*
|
|
43227
|
+
* @private internal utility of `ptbk coder` wait handling
|
|
43228
|
+
*/
|
|
43229
|
+
function parseOptionalWaitDuration(value, defaultMs) {
|
|
43230
|
+
if (typeof value !== 'string' || value === '') {
|
|
43231
|
+
return defaultMs;
|
|
43232
|
+
}
|
|
43233
|
+
return parseDuration(value);
|
|
43234
|
+
}
|
|
43235
|
+
/**
|
|
43236
|
+
* Parses an optional Commander period duration string and returns the resolved milliseconds.
|
|
43237
|
+
*
|
|
43238
|
+
* Returns `undefined` when the flag was not provided or was provided without a non-empty value,
|
|
43239
|
+
* which means the command runs only once instead of repeating itself.
|
|
43240
|
+
*
|
|
43241
|
+
* @throws {NotAllowed} When the duration is not a positive one, because a non-positive period
|
|
43242
|
+
* would repeat the command without ever pausing between two rounds
|
|
43243
|
+
*
|
|
43244
|
+
* @private internal utility of `ptbk coder` wait handling
|
|
43245
|
+
*/
|
|
43246
|
+
function parseOptionalPeriodDuration(optionName, value) {
|
|
43247
|
+
if (typeof value !== 'string' || value === '') {
|
|
43248
|
+
return undefined;
|
|
43249
|
+
}
|
|
43250
|
+
const periodMs = parseDuration(value);
|
|
43251
|
+
if (periodMs <= 0) {
|
|
43252
|
+
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
43253
|
+
Invalid value for \`${optionName}\`: \`${value}\`.
|
|
43254
|
+
|
|
43255
|
+
Use a **positive** duration like \`5h\`, \`30m\` or \`1h30m\`.
|
|
43256
|
+
`));
|
|
43257
|
+
}
|
|
43258
|
+
return periodMs;
|
|
43259
|
+
}
|
|
43260
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
43261
|
+
|
|
42460
43262
|
/**
|
|
42461
43263
|
* Initializes `coder ping` command for Promptbook CLI utilities
|
|
42462
43264
|
*
|
|
@@ -42475,6 +43277,7 @@
|
|
|
42475
43277
|
- Verifies that the selected harness, model, thinking level and authentication really work
|
|
42476
43278
|
- Reports the answer of the harness, the response time and the reported usage
|
|
42477
43279
|
- Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
|
|
43280
|
+
- Optional --period keeps the quota window refreshing by pinging once per period until stopped
|
|
42478
43281
|
- Leaves the project exactly as it was — nothing is read, written, changed or committed
|
|
42479
43282
|
- Checks that the selected harness is installed globally and up to date unless --no-harness-update is used
|
|
42480
43283
|
- Use --no-ui to stream the raw harness output instead of only the compact result
|
|
@@ -42482,21 +43285,34 @@
|
|
|
42482
43285
|
addPromptRunnerSelectionOptions(command);
|
|
42483
43286
|
addHarnessUpdateOption(command);
|
|
42484
43287
|
addPromptRunnerRuntimeOptions(command);
|
|
43288
|
+
command.option('--period <duration>', _spaceTrim.spaceTrim(`
|
|
43289
|
+
Keep pinging once per period instead of pinging only once.
|
|
43290
|
+
Accepts durations like 5h, 30m, 1h30m and repeats until it is stopped with CTRL+C.
|
|
43291
|
+
`));
|
|
42485
43292
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
43293
|
+
const { period: periodValue } = cliOptions;
|
|
42486
43294
|
const runnerOptions = normalizePromptRunnerSelectionCliOptions(cliOptions, { isAgentRequired: true });
|
|
42487
43295
|
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
43296
|
+
// Note: The period is validated before the harness installation check, so a mistyped duration fails fast
|
|
43297
|
+
const periodMs = parseOptionalPeriodDuration('--period', periodValue);
|
|
42488
43298
|
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
42489
|
-
|
|
42490
|
-
const { pingCoderHarness } = await Promise.resolve().then(function () { return pingCoderHarness$1; });
|
|
42491
|
-
const { printCoderPingResult } = await Promise.resolve().then(function () { return printCoderPingResult$1; });
|
|
42492
|
-
const result = await pingCoderHarness({
|
|
43299
|
+
const pingOptions = {
|
|
42493
43300
|
agentName: runnerOptions.agentName,
|
|
42494
43301
|
model: runnerOptions.model,
|
|
42495
43302
|
thinkingLevel: runnerOptions.thinkingLevel,
|
|
42496
43303
|
allowCredits: runnerOptions.allowCredits,
|
|
42497
43304
|
shouldPrintLiveOutput: runnerOptions.noUi,
|
|
42498
|
-
}
|
|
42499
|
-
|
|
43305
|
+
};
|
|
43306
|
+
// Note: Import the ping dynamically to avoid loading heavy dependencies until needed
|
|
43307
|
+
if (periodMs !== undefined) {
|
|
43308
|
+
const { pingCoderHarnessPeriodically } = await Promise.resolve().then(function () { return pingCoderHarnessPeriodically$1; });
|
|
43309
|
+
// Note: This never returns - it keeps pinging until the user stops the process
|
|
43310
|
+
await pingCoderHarnessPeriodically({ ...pingOptions, periodMs });
|
|
43311
|
+
return;
|
|
43312
|
+
}
|
|
43313
|
+
const { pingCoderHarness } = await Promise.resolve().then(function () { return pingCoderHarness$1; });
|
|
43314
|
+
const { printCoderPingResult } = await Promise.resolve().then(function () { return printCoderPingResult$1; });
|
|
43315
|
+
printCoderPingResult(await pingCoderHarness(pingOptions));
|
|
42500
43316
|
}));
|
|
42501
43317
|
}
|
|
42502
43318
|
// Note: [🟡] Code for CLI command [ping](src/cli/cli-commands/coder/ping.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -42933,27 +43749,6 @@
|
|
|
42933
43749
|
return TEST_BEFORE_MODE_VALUES.includes(value);
|
|
42934
43750
|
}
|
|
42935
43751
|
|
|
42936
|
-
/**
|
|
42937
|
-
* Default wait duration applied before retrying a prompt round after an error (10 minutes).
|
|
42938
|
-
*
|
|
42939
|
-
* @private internal constant of `ptbk coder` wait handling
|
|
42940
|
-
*/
|
|
42941
|
-
const DEFAULT_WAIT_AFTER_ERROR_MS$1 = 10 * 60 * 1000;
|
|
42942
|
-
/**
|
|
42943
|
-
* Parses an optional Commander duration string and returns the resolved milliseconds.
|
|
42944
|
-
*
|
|
42945
|
-
* Returns `defaultMs` when the flag was not provided or was provided without a non-empty value.
|
|
42946
|
-
*
|
|
42947
|
-
* @private internal utility of `ptbk coder` wait handling
|
|
42948
|
-
*/
|
|
42949
|
-
function parseOptionalWaitDuration(value, defaultMs) {
|
|
42950
|
-
if (typeof value !== 'string' || value === '') {
|
|
42951
|
-
return defaultMs;
|
|
42952
|
-
}
|
|
42953
|
-
return parseDuration(value);
|
|
42954
|
-
}
|
|
42955
|
-
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
42956
|
-
|
|
42957
43752
|
/**
|
|
42958
43753
|
* Initializes `coder run` command for Promptbook CLI utilities
|
|
42959
43754
|
*
|
|
@@ -66995,7 +67790,7 @@
|
|
|
66995
67790
|
padBook(validateBook(_spaceTrim.spaceTrim(`
|
|
66996
67791
|
AI Avatar
|
|
66997
67792
|
|
|
66998
|
-
|
|
67793
|
+
GOAL Help users with their tasks as a friendly AI assistant.
|
|
66999
67794
|
`)));
|
|
67000
67795
|
// <- Note: Not using book`...` notation to avoid strange error in jest unit tests `TypeError: (0 , book_notation_1.book) is not a function`
|
|
67001
67796
|
// <- TODO: [🐱🚀] `GENESIS_BOOK` / `ADAM_BOOK` in `/agents/adam.book`
|
|
@@ -72692,6 +73487,23 @@
|
|
|
72692
73487
|
findUnwrittenPrompts: findUnwrittenPrompts
|
|
72693
73488
|
});
|
|
72694
73489
|
|
|
73490
|
+
/**
|
|
73491
|
+
* Formats one unknown error-like value into its readable message without the stack trace.
|
|
73492
|
+
*
|
|
73493
|
+
* Use this instead of `formatUnknownErrorDetails` whenever the text is shown to the user, for example
|
|
73494
|
+
* inside a branded error, where the stack of the wrapped error would only bury the actual cause.
|
|
73495
|
+
*/
|
|
73496
|
+
function formatUnknownErrorMessage(error) {
|
|
73497
|
+
if (error instanceof Error) {
|
|
73498
|
+
return error.message;
|
|
73499
|
+
}
|
|
73500
|
+
if (typeof error === 'string') {
|
|
73501
|
+
return error;
|
|
73502
|
+
}
|
|
73503
|
+
const serializedError = JSON.stringify(error, null, 2);
|
|
73504
|
+
return serializedError !== null && serializedError !== void 0 ? serializedError : String(error);
|
|
73505
|
+
}
|
|
73506
|
+
|
|
72695
73507
|
/**
|
|
72696
73508
|
* Builds a normalized temporary shell script path for prompt runners.
|
|
72697
73509
|
*/
|
|
@@ -72929,6 +73741,60 @@
|
|
|
72929
73741
|
printCoderPingResult: printCoderPingResult
|
|
72930
73742
|
});
|
|
72931
73743
|
|
|
73744
|
+
/**
|
|
73745
|
+
* How often the countdown to the next periodic ping is reported to the console (30 minutes).
|
|
73746
|
+
*
|
|
73747
|
+
* A period like `5h` is meant to be left running unattended, so the countdown is deliberately
|
|
73748
|
+
* coarse — it is a sign of life, not a progress bar.
|
|
73749
|
+
*/
|
|
73750
|
+
const CODER_PING_COUNTDOWN_UPDATE_INTERVAL_MS = 30 * 60 * 1000;
|
|
73751
|
+
/**
|
|
73752
|
+
* Pings the selected harness and model once per period until the process is stopped.
|
|
73753
|
+
*
|
|
73754
|
+
* This keeps the quota window of the harness refreshing without any real work, so the window is
|
|
73755
|
+
* always open by the time you need it. The loop never ends on its own — it is stopped with `CTRL+C`
|
|
73756
|
+
* or by killing the process — therefore a failing ping is reported and the next period is started
|
|
73757
|
+
* instead of tearing the whole loop down.
|
|
73758
|
+
*/
|
|
73759
|
+
async function pingCoderHarnessPeriodically(options) {
|
|
73760
|
+
const { periodMs, ...pingOptions } = options;
|
|
73761
|
+
console.info(colors__default["default"].gray(`🏓 Pinging every ${formatDurationMs(periodMs)} until stopped with CTRL+C`));
|
|
73762
|
+
// Note: The loop is intentionally endless - only `CTRL+C` or killing the process ends it
|
|
73763
|
+
for (;;) {
|
|
73764
|
+
const nextPingTimeMs = Date.now() + periodMs;
|
|
73765
|
+
await reportOneCoderPing(pingOptions);
|
|
73766
|
+
await waitUntilNextCoderPing(nextPingTimeMs);
|
|
73767
|
+
}
|
|
73768
|
+
}
|
|
73769
|
+
/**
|
|
73770
|
+
* Sends and reports one ping of the endless loop, keeping the loop alive when the harness fails.
|
|
73771
|
+
*/
|
|
73772
|
+
async function reportOneCoderPing(options) {
|
|
73773
|
+
try {
|
|
73774
|
+
printCoderPingResult(await pingCoderHarness(options));
|
|
73775
|
+
}
|
|
73776
|
+
catch (error) {
|
|
73777
|
+
console.error(colors__default["default"].red(`🏓 Ping failed: ${formatUnknownErrorMessage(error)}`));
|
|
73778
|
+
}
|
|
73779
|
+
}
|
|
73780
|
+
/**
|
|
73781
|
+
* Waits until the wall-clock time of the next ping, reporting how much of the period is left.
|
|
73782
|
+
*/
|
|
73783
|
+
async function waitUntilNextCoderPing(nextPingTimeMs) {
|
|
73784
|
+
await waitUntilWorldTimeDeadline({
|
|
73785
|
+
deadlineTimeMs: nextPingTimeMs,
|
|
73786
|
+
pollIntervalMs: CODER_PING_COUNTDOWN_UPDATE_INTERVAL_MS,
|
|
73787
|
+
onTick(remainingDurationMs) {
|
|
73788
|
+
console.info(colors__default["default"].gray(` Next ping in ${formatDurationMs(remainingDurationMs)}`));
|
|
73789
|
+
},
|
|
73790
|
+
});
|
|
73791
|
+
}
|
|
73792
|
+
|
|
73793
|
+
var pingCoderHarnessPeriodically$1 = /*#__PURE__*/Object.freeze({
|
|
73794
|
+
__proto__: null,
|
|
73795
|
+
pingCoderHarnessPeriodically: pingCoderHarnessPeriodically
|
|
73796
|
+
});
|
|
73797
|
+
|
|
72932
73798
|
/**
|
|
72933
73799
|
* Default wait duration applied before retrying a failed prompt round.
|
|
72934
73800
|
*/
|
|
@@ -75762,23 +76628,6 @@
|
|
|
75762
76628
|
return getPromptbookTemporaryPath(CODER_ISOLATION_WORKTREES_DIRECTORY_NAME, taskName);
|
|
75763
76629
|
}
|
|
75764
76630
|
|
|
75765
|
-
/**
|
|
75766
|
-
* Formats one unknown error-like value into its readable message without the stack trace.
|
|
75767
|
-
*
|
|
75768
|
-
* Use this instead of `formatUnknownErrorDetails` whenever the text is shown to the user, for example
|
|
75769
|
-
* inside a branded error, where the stack of the wrapped error would only bury the actual cause.
|
|
75770
|
-
*/
|
|
75771
|
-
function formatUnknownErrorMessage(error) {
|
|
75772
|
-
if (error instanceof Error) {
|
|
75773
|
-
return error.message;
|
|
75774
|
-
}
|
|
75775
|
-
if (typeof error === 'string') {
|
|
75776
|
-
return error;
|
|
75777
|
-
}
|
|
75778
|
-
const serializedError = JSON.stringify(error, null, 2);
|
|
75779
|
-
return serializedError !== null && serializedError !== void 0 ? serializedError : String(error);
|
|
75780
|
-
}
|
|
75781
|
-
|
|
75782
76631
|
/**
|
|
75783
76632
|
* Git configuration key which lets Git read, write and delete files whose absolute path is longer than
|
|
75784
76633
|
* the Windows `MAX_PATH` limit of 260 characters.
|