@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/esm/index.es.js
CHANGED
|
@@ -4,7 +4,7 @@ import _spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
|
4
4
|
import { writeFile, stat, mkdir, readFile, readdir, rm, cp, lstat, symlink, rename, unlink, appendFile, realpath, copyFile, access, constants, watch, rmdir } from 'fs/promises';
|
|
5
5
|
import { join, delimiter, relative, basename, resolve, dirname, isAbsolute, extname } from 'path';
|
|
6
6
|
import { createHash, randomBytes } from 'crypto';
|
|
7
|
-
import { spawn, spawnSync } from 'child_process';
|
|
7
|
+
import { spawn, spawnSync, execFile } from 'child_process';
|
|
8
8
|
import moment from 'moment';
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import { createWriteStream, mkdirSync, writeFileSync, statSync, readFileSync, existsSync, promises } from 'fs';
|
|
@@ -48,7 +48,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
48
48
|
* @generated
|
|
49
49
|
* @see https://github.com/webgptorg/promptbook
|
|
50
50
|
*/
|
|
51
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-
|
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-18';
|
|
52
52
|
/**
|
|
53
53
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
54
54
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -2207,7 +2207,7 @@ async function isExistingFile$4(path) {
|
|
|
2207
2207
|
*/
|
|
2208
2208
|
async function ensureDirectory(projectPath, relativeDirectoryPath) {
|
|
2209
2209
|
const directoryPath = join(projectPath, relativeDirectoryPath);
|
|
2210
|
-
const isDirectoryExisting = await isExistingDirectory$
|
|
2210
|
+
const isDirectoryExisting = await isExistingDirectory$2(directoryPath);
|
|
2211
2211
|
if (!isDirectoryExisting) {
|
|
2212
2212
|
await mkdir(directoryPath, { recursive: true });
|
|
2213
2213
|
return 'created';
|
|
@@ -2217,7 +2217,7 @@ async function ensureDirectory(projectPath, relativeDirectoryPath) {
|
|
|
2217
2217
|
/**
|
|
2218
2218
|
* Checks whether a path exists and is a directory.
|
|
2219
2219
|
*/
|
|
2220
|
-
async function isExistingDirectory$
|
|
2220
|
+
async function isExistingDirectory$2(path) {
|
|
2221
2221
|
try {
|
|
2222
2222
|
return (await stat(path)).isDirectory();
|
|
2223
2223
|
}
|
|
@@ -5716,6 +5716,12 @@ class FromCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
5716
5716
|
|
|
5717
5717
|
Inherits agent source from another agent.
|
|
5718
5718
|
|
|
5719
|
+
Every agent inherits from the core agent \`@Adam\` unless it says otherwise, so writing no ${this.type} at all
|
|
5720
|
+
is the same as writing \`${this.type} @Adam\`. Write \`${this.type} @Null\` to inherit from nothing.
|
|
5721
|
+
|
|
5722
|
+
An agent has exactly one parent, so when ${this.type} is written more than once, the last one wins and
|
|
5723
|
+
overrides every earlier one.
|
|
5724
|
+
|
|
5719
5725
|
## Examples
|
|
5720
5726
|
|
|
5721
5727
|
\`\`\`book
|
|
@@ -5724,6 +5730,13 @@ class FromCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
5724
5730
|
FROM https://s6.ptbk.io/benjamin-white
|
|
5725
5731
|
RULE Speak only in English.
|
|
5726
5732
|
\`\`\`
|
|
5733
|
+
|
|
5734
|
+
\`\`\`book
|
|
5735
|
+
My Standalone Agent
|
|
5736
|
+
|
|
5737
|
+
FROM @Null
|
|
5738
|
+
RULE Speak only in English.
|
|
5739
|
+
\`\`\`
|
|
5727
5740
|
`);
|
|
5728
5741
|
}
|
|
5729
5742
|
applyToAgentModelRequirements(requirements, content) {
|
|
@@ -30572,6 +30585,385 @@ function buildPromptTestScriptPath(scriptPath) {
|
|
|
30572
30585
|
return `${scriptPath}.test.sh`;
|
|
30573
30586
|
}
|
|
30574
30587
|
|
|
30588
|
+
/**
|
|
30589
|
+
* Lists the direct project directories of one agent folder.
|
|
30590
|
+
*
|
|
30591
|
+
* @param agentFolderPath - Absolute path of the local agent folder.
|
|
30592
|
+
* @returns Project directory names, or an empty list when the agent has no projects folder.
|
|
30593
|
+
*/
|
|
30594
|
+
async function listAgentProjectDirectoryNames(agentFolderPath) {
|
|
30595
|
+
try {
|
|
30596
|
+
const projectsRootEntries = await readdir(join(agentFolderPath, AGENT_PROJECTS_DIRECTORY_PATH), {
|
|
30597
|
+
withFileTypes: true,
|
|
30598
|
+
});
|
|
30599
|
+
return projectsRootEntries
|
|
30600
|
+
.filter((projectsRootEntry) => projectsRootEntry.isDirectory())
|
|
30601
|
+
.map((projectDirectoryEntry) => projectDirectoryEntry.name);
|
|
30602
|
+
}
|
|
30603
|
+
catch (_a) {
|
|
30604
|
+
return [];
|
|
30605
|
+
}
|
|
30606
|
+
}
|
|
30607
|
+
|
|
30608
|
+
/**
|
|
30609
|
+
* Largest git output kept in memory, so an enormous diff can never exhaust the runner process.
|
|
30610
|
+
*/
|
|
30611
|
+
const AGENT_PROJECT_GIT_OUTPUT_MAX_BYTES = 8 * 1024 * 1024;
|
|
30612
|
+
/**
|
|
30613
|
+
* Time after which one git command of a project repository is given up on.
|
|
30614
|
+
*/
|
|
30615
|
+
const AGENT_PROJECT_GIT_TIMEOUT_MS = 60 * 1000;
|
|
30616
|
+
/**
|
|
30617
|
+
* Author and committer used for project commits when no coding-agent identity is configured.
|
|
30618
|
+
*
|
|
30619
|
+
* A project repository is created by the runner on a server which usually has no git identity at
|
|
30620
|
+
* all, so committing must never depend on the machine configuration.
|
|
30621
|
+
*/
|
|
30622
|
+
const AGENT_PROJECT_GIT_FALLBACK_IDENTITY = {
|
|
30623
|
+
GIT_AUTHOR_NAME: 'Promptbook Agent',
|
|
30624
|
+
GIT_AUTHOR_EMAIL: 'agent@promptbook.studio',
|
|
30625
|
+
GIT_COMMITTER_NAME: 'Promptbook Agent',
|
|
30626
|
+
GIT_COMMITTER_EMAIL: 'agent@promptbook.studio',
|
|
30627
|
+
};
|
|
30628
|
+
/**
|
|
30629
|
+
* Runs one git command inside one agent project directory.
|
|
30630
|
+
*
|
|
30631
|
+
* Commands are executed without a shell and with an explicit argument list, so a project name or
|
|
30632
|
+
* a file path can never be interpreted as a shell fragment. A failing command is reported through
|
|
30633
|
+
* `isSuccessful` instead of throwing, because git uses the exit code to answer questions such as
|
|
30634
|
+
* "is there anything staged" and because auto-committing a project must never fail an answer the
|
|
30635
|
+
* agent already produced.
|
|
30636
|
+
*
|
|
30637
|
+
* @param options - Project directory and the git arguments to run there.
|
|
30638
|
+
* @returns Outcome of the command.
|
|
30639
|
+
*/
|
|
30640
|
+
async function runAgentProjectGitCommand(options) {
|
|
30641
|
+
return await new Promise((resolve) => {
|
|
30642
|
+
execFile('git', [...options.args], {
|
|
30643
|
+
cwd: options.projectPath,
|
|
30644
|
+
env: { ...process.env, ...AGENT_PROJECT_GIT_FALLBACK_IDENTITY, ...(buildAgentGitEnv() || {}) },
|
|
30645
|
+
maxBuffer: AGENT_PROJECT_GIT_OUTPUT_MAX_BYTES,
|
|
30646
|
+
timeout: AGENT_PROJECT_GIT_TIMEOUT_MS,
|
|
30647
|
+
windowsHide: true,
|
|
30648
|
+
}, (error, stdout) => {
|
|
30649
|
+
resolve({
|
|
30650
|
+
isSuccessful: !error,
|
|
30651
|
+
output: stripTrailingNewline(stdout || ''),
|
|
30652
|
+
});
|
|
30653
|
+
});
|
|
30654
|
+
});
|
|
30655
|
+
}
|
|
30656
|
+
/**
|
|
30657
|
+
* Removes the single trailing newline git appends to its output.
|
|
30658
|
+
*
|
|
30659
|
+
* @param output - Raw command output.
|
|
30660
|
+
* @returns Output without its trailing newline.
|
|
30661
|
+
*
|
|
30662
|
+
* @private helper of `runAgentProjectGitCommand`
|
|
30663
|
+
*/
|
|
30664
|
+
function stripTrailingNewline(output) {
|
|
30665
|
+
return output.replace(/\r?\n$/u, '');
|
|
30666
|
+
}
|
|
30667
|
+
|
|
30668
|
+
/**
|
|
30669
|
+
* Branch created for a project repository, so every agent project starts with the same history.
|
|
30670
|
+
*/
|
|
30671
|
+
const AGENT_PROJECT_GIT_INITIAL_BRANCH = 'main';
|
|
30672
|
+
/**
|
|
30673
|
+
* Paths kept out of a project repository created by the runner.
|
|
30674
|
+
*
|
|
30675
|
+
* Only a project which brings no ignore rules of its own receives these, and they cover exactly
|
|
30676
|
+
* the two things that must never enter an automatic commit: installed dependencies and secrets.
|
|
30677
|
+
*/
|
|
30678
|
+
const AGENT_PROJECT_GIT_DEFAULT_IGNORE_PATHS = spaceTrim$1(`
|
|
30679
|
+
node_modules/
|
|
30680
|
+
.env
|
|
30681
|
+
.env.*
|
|
30682
|
+
`);
|
|
30683
|
+
/**
|
|
30684
|
+
* Makes sure one agent project is a git repository of its own.
|
|
30685
|
+
*
|
|
30686
|
+
* A project which is already tracked by a repository around the agent folder is deliberately left
|
|
30687
|
+
* alone: initializing a repository inside it would turn it into an embedded repository and break
|
|
30688
|
+
* the history that already covers it.
|
|
30689
|
+
*
|
|
30690
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30691
|
+
* @returns How the project relates to git after this call.
|
|
30692
|
+
*/
|
|
30693
|
+
async function ensureAgentProjectGitRepository(projectPath) {
|
|
30694
|
+
if (await isExistingDirectory$1(join(projectPath, '.git'))) {
|
|
30695
|
+
return 'own-repository';
|
|
30696
|
+
}
|
|
30697
|
+
if (await isProjectTrackedByOuterRepository(projectPath)) {
|
|
30698
|
+
return 'tracked-elsewhere';
|
|
30699
|
+
}
|
|
30700
|
+
if (!(await initializeAgentProjectGitRepository(projectPath))) {
|
|
30701
|
+
return 'unavailable';
|
|
30702
|
+
}
|
|
30703
|
+
await writeDefaultAgentProjectGitignoreIfMissing(projectPath);
|
|
30704
|
+
return 'own-repository';
|
|
30705
|
+
}
|
|
30706
|
+
/**
|
|
30707
|
+
* Creates the repository of one project, naming its first branch when git supports it.
|
|
30708
|
+
*
|
|
30709
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30710
|
+
* @returns `true` when the project is a repository afterwards.
|
|
30711
|
+
*
|
|
30712
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30713
|
+
*/
|
|
30714
|
+
async function initializeAgentProjectGitRepository(projectPath) {
|
|
30715
|
+
const initResult = await runAgentProjectGitCommand({
|
|
30716
|
+
projectPath,
|
|
30717
|
+
args: ['init', `--initial-branch=${AGENT_PROJECT_GIT_INITIAL_BRANCH}`],
|
|
30718
|
+
});
|
|
30719
|
+
if (initResult.isSuccessful) {
|
|
30720
|
+
return true;
|
|
30721
|
+
}
|
|
30722
|
+
// Note: `--initial-branch` needs git 2.28, so an older git still gets its repository
|
|
30723
|
+
return (await runAgentProjectGitCommand({ projectPath, args: ['init'] })).isSuccessful;
|
|
30724
|
+
}
|
|
30725
|
+
/**
|
|
30726
|
+
* Checks whether a repository around the agent folder already tracks the project files.
|
|
30727
|
+
*
|
|
30728
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30729
|
+
* @returns `true` when an outer repository tracks at least one file of the project.
|
|
30730
|
+
*
|
|
30731
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30732
|
+
*/
|
|
30733
|
+
async function isProjectTrackedByOuterRepository(projectPath) {
|
|
30734
|
+
const trackedFilesResult = await runAgentProjectGitCommand({
|
|
30735
|
+
projectPath,
|
|
30736
|
+
args: ['ls-files', '--', '.'],
|
|
30737
|
+
});
|
|
30738
|
+
return trackedFilesResult.isSuccessful && trackedFilesResult.output.trim().length > 0;
|
|
30739
|
+
}
|
|
30740
|
+
/**
|
|
30741
|
+
* Writes the default ignore rules into a freshly initialized project repository.
|
|
30742
|
+
*
|
|
30743
|
+
* A project which already brings its own rules keeps them untouched.
|
|
30744
|
+
*
|
|
30745
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30746
|
+
*
|
|
30747
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30748
|
+
*/
|
|
30749
|
+
async function writeDefaultAgentProjectGitignoreIfMissing(projectPath) {
|
|
30750
|
+
const gitignorePath = join(projectPath, '.gitignore');
|
|
30751
|
+
try {
|
|
30752
|
+
await stat(gitignorePath);
|
|
30753
|
+
return;
|
|
30754
|
+
}
|
|
30755
|
+
catch (_a) {
|
|
30756
|
+
// Note: A project without ignore rules would commit its installed dependencies
|
|
30757
|
+
}
|
|
30758
|
+
await writeFile(gitignorePath, `${AGENT_PROJECT_GIT_DEFAULT_IGNORE_PATHS}\n`, 'utf-8');
|
|
30759
|
+
}
|
|
30760
|
+
/**
|
|
30761
|
+
* Checks whether one path is an existing directory.
|
|
30762
|
+
*
|
|
30763
|
+
* @param directoryPath - Absolute path to check.
|
|
30764
|
+
* @returns `true` when the path exists and is a directory.
|
|
30765
|
+
*
|
|
30766
|
+
* @private helper of `ensureAgentProjectGitRepository`
|
|
30767
|
+
*/
|
|
30768
|
+
async function isExistingDirectory$1(directoryPath) {
|
|
30769
|
+
try {
|
|
30770
|
+
return (await stat(directoryPath)).isDirectory();
|
|
30771
|
+
}
|
|
30772
|
+
catch (_a) {
|
|
30773
|
+
return false;
|
|
30774
|
+
}
|
|
30775
|
+
}
|
|
30776
|
+
|
|
30777
|
+
/**
|
|
30778
|
+
* Largest diff carried into a chat, so one huge commit cannot bloat every message payload.
|
|
30779
|
+
*/
|
|
30780
|
+
const AGENT_PROJECT_DIFF_MAX_LENGTH = 20000;
|
|
30781
|
+
/**
|
|
30782
|
+
* Describes the latest commit of one agent project repository.
|
|
30783
|
+
*
|
|
30784
|
+
* @param options - Project directory and the project name the description is reported under.
|
|
30785
|
+
* @returns Description of the commit, or `null` when git could not describe it.
|
|
30786
|
+
*/
|
|
30787
|
+
async function readAgentProjectCommitChange(options) {
|
|
30788
|
+
const { projectPath, projectName } = options;
|
|
30789
|
+
const [commitHashResult, committedAtResult, numstatResult, diffResult] = await Promise.all([
|
|
30790
|
+
runAgentProjectGitCommand({ projectPath, args: ['rev-parse', 'HEAD'] }),
|
|
30791
|
+
runAgentProjectGitCommand({ projectPath, args: ['show', '--no-patch', '--format=%cI', 'HEAD'] }),
|
|
30792
|
+
runAgentProjectGitCommand({ projectPath, args: ['show', '--numstat', '--format=', 'HEAD'] }),
|
|
30793
|
+
runAgentProjectGitCommand({ projectPath, args: ['show', '--patch', '--format=', 'HEAD'] }),
|
|
30794
|
+
]);
|
|
30795
|
+
if (!commitHashResult.isSuccessful || commitHashResult.output.trim().length === 0) {
|
|
30796
|
+
return null;
|
|
30797
|
+
}
|
|
30798
|
+
const changedFiles = parseAgentProjectNumstat(numstatResult.isSuccessful ? numstatResult.output : '');
|
|
30799
|
+
const diff = diffResult.isSuccessful ? diffResult.output : '';
|
|
30800
|
+
return {
|
|
30801
|
+
projectName,
|
|
30802
|
+
commitHash: commitHashResult.output.trim(),
|
|
30803
|
+
committedAt: resolveCommittedAt(committedAtResult.isSuccessful ? committedAtResult.output : ''),
|
|
30804
|
+
changedFiles,
|
|
30805
|
+
insertionCount: sumChangedFileCounts(changedFiles, 'insertionCount'),
|
|
30806
|
+
deletionCount: sumChangedFileCounts(changedFiles, 'deletionCount'),
|
|
30807
|
+
diff: diff.slice(0, AGENT_PROJECT_DIFF_MAX_LENGTH),
|
|
30808
|
+
isDiffTruncated: diff.length > AGENT_PROJECT_DIFF_MAX_LENGTH,
|
|
30809
|
+
};
|
|
30810
|
+
}
|
|
30811
|
+
/**
|
|
30812
|
+
* Parses the `git show --numstat` output into changed files.
|
|
30813
|
+
*
|
|
30814
|
+
* Binary files report `-` instead of line counts, which is kept as a zero-line change so the file
|
|
30815
|
+
* is still listed as touched.
|
|
30816
|
+
*
|
|
30817
|
+
* @param numstatOutput - Raw numstat output.
|
|
30818
|
+
* @returns Changed files in the order git reported them.
|
|
30819
|
+
*
|
|
30820
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30821
|
+
*/
|
|
30822
|
+
function parseAgentProjectNumstat(numstatOutput) {
|
|
30823
|
+
return numstatOutput
|
|
30824
|
+
.split(/\r?\n/u)
|
|
30825
|
+
.map((numstatLine) => numstatLine.split('\t'))
|
|
30826
|
+
.filter((numstatColumns) => numstatColumns.length >= 3 && numstatColumns[2].trim().length > 0)
|
|
30827
|
+
.map((numstatColumns) => ({
|
|
30828
|
+
path: numstatColumns.slice(2).join('\t').trim(),
|
|
30829
|
+
insertionCount: parseChangedLineCount(numstatColumns[0]),
|
|
30830
|
+
deletionCount: parseChangedLineCount(numstatColumns[1]),
|
|
30831
|
+
}));
|
|
30832
|
+
}
|
|
30833
|
+
/**
|
|
30834
|
+
* Parses one numstat line count.
|
|
30835
|
+
*
|
|
30836
|
+
* @param rawLineCount - Raw numstat column.
|
|
30837
|
+
* @returns Parsed count, or `0` for binary files and unparseable columns.
|
|
30838
|
+
*
|
|
30839
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30840
|
+
*/
|
|
30841
|
+
function parseChangedLineCount(rawLineCount) {
|
|
30842
|
+
const parsedLineCount = Number.parseInt(rawLineCount.trim(), 10);
|
|
30843
|
+
return Number.isFinite(parsedLineCount) && parsedLineCount >= 0 ? parsedLineCount : 0;
|
|
30844
|
+
}
|
|
30845
|
+
/**
|
|
30846
|
+
* Sums one line-count field across all changed files.
|
|
30847
|
+
*
|
|
30848
|
+
* @param changedFiles - Changed files of the commit.
|
|
30849
|
+
* @param countName - Field to sum.
|
|
30850
|
+
* @returns Total count.
|
|
30851
|
+
*
|
|
30852
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30853
|
+
*/
|
|
30854
|
+
function sumChangedFileCounts(changedFiles, countName) {
|
|
30855
|
+
return changedFiles.reduce((total, changedFile) => total + changedFile[countName], 0);
|
|
30856
|
+
}
|
|
30857
|
+
/**
|
|
30858
|
+
* Normalizes the commit timestamp git reported.
|
|
30859
|
+
*
|
|
30860
|
+
* @param rawCommittedAt - Raw ISO timestamp from git.
|
|
30861
|
+
* @returns Usable ISO timestamp, falling back to the current time when git reported none.
|
|
30862
|
+
*
|
|
30863
|
+
* @private helper of `readAgentProjectCommitChange`
|
|
30864
|
+
*/
|
|
30865
|
+
function resolveCommittedAt(rawCommittedAt) {
|
|
30866
|
+
const trimmedCommittedAt = rawCommittedAt.trim();
|
|
30867
|
+
if (trimmedCommittedAt.length === 0 || !Number.isFinite(Date.parse(trimmedCommittedAt))) {
|
|
30868
|
+
return new Date().toISOString();
|
|
30869
|
+
}
|
|
30870
|
+
return new Date(trimmedCommittedAt).toISOString();
|
|
30871
|
+
}
|
|
30872
|
+
|
|
30873
|
+
/**
|
|
30874
|
+
* Commits everything one answered message changed inside one agent project.
|
|
30875
|
+
*
|
|
30876
|
+
* The project is turned into a git repository first when it is not one yet, so the work of every
|
|
30877
|
+
* answer stays recoverable and reviewable as a normal commit history.
|
|
30878
|
+
*
|
|
30879
|
+
* @param options - Project identity and the commit message describing the answered message.
|
|
30880
|
+
* @returns What was committed, or `null` when the project changed nothing or cannot be committed.
|
|
30881
|
+
*/
|
|
30882
|
+
async function commitAgentProjectChanges(options) {
|
|
30883
|
+
const { projectPath, projectName, commitMessage } = options;
|
|
30884
|
+
if ((await ensureAgentProjectGitRepository(projectPath)) !== 'own-repository') {
|
|
30885
|
+
return null;
|
|
30886
|
+
}
|
|
30887
|
+
const stageResult = await runAgentProjectGitCommand({ projectPath, args: ['add', '--all', '--', '.'] });
|
|
30888
|
+
if (!stageResult.isSuccessful) {
|
|
30889
|
+
return null;
|
|
30890
|
+
}
|
|
30891
|
+
if (!(await hasStagedAgentProjectChanges(projectPath))) {
|
|
30892
|
+
return null;
|
|
30893
|
+
}
|
|
30894
|
+
const commitResult = await runAgentProjectGitCommand({
|
|
30895
|
+
projectPath,
|
|
30896
|
+
args: ['commit', '--message', commitMessage],
|
|
30897
|
+
});
|
|
30898
|
+
if (!commitResult.isSuccessful) {
|
|
30899
|
+
return null;
|
|
30900
|
+
}
|
|
30901
|
+
return await readAgentProjectCommitChange({ projectPath, projectName });
|
|
30902
|
+
}
|
|
30903
|
+
/**
|
|
30904
|
+
* Checks whether the project index holds anything to commit.
|
|
30905
|
+
*
|
|
30906
|
+
* @param projectPath - Absolute path of the project directory.
|
|
30907
|
+
* @returns `true` when committing would create a non-empty commit.
|
|
30908
|
+
*
|
|
30909
|
+
* @private helper of `commitAgentProjectChanges`
|
|
30910
|
+
*/
|
|
30911
|
+
async function hasStagedAgentProjectChanges(projectPath) {
|
|
30912
|
+
// Note: `--quiet` makes git answer through its exit code — success means nothing is staged
|
|
30913
|
+
const stagedChangesResult = await runAgentProjectGitCommand({
|
|
30914
|
+
projectPath,
|
|
30915
|
+
args: ['diff', '--cached', '--quiet'],
|
|
30916
|
+
});
|
|
30917
|
+
return !stagedChangesResult.isSuccessful;
|
|
30918
|
+
}
|
|
30919
|
+
|
|
30920
|
+
/**
|
|
30921
|
+
* Commits what one answered message changed in every project of one agent.
|
|
30922
|
+
*
|
|
30923
|
+
* Every project of an agent is its own git repository, so each answer which modified one becomes a
|
|
30924
|
+
* commit there. The projects are committed one after another because they share the git executable
|
|
30925
|
+
* and because an agent works with a handful of projects at most.
|
|
30926
|
+
*
|
|
30927
|
+
* Committing is best-effort bookkeeping around an answer the agent already produced: a project
|
|
30928
|
+
* whose commit fails is reported to the console and skipped instead of failing the message.
|
|
30929
|
+
*
|
|
30930
|
+
* @param options - Agent folder and the commit message describing the answered message.
|
|
30931
|
+
* @returns What was committed, one entry per project the message really changed.
|
|
30932
|
+
*/
|
|
30933
|
+
async function commitAnsweredMessageProjectChanges(options) {
|
|
30934
|
+
const { agentFolderPath, commitMessage } = options;
|
|
30935
|
+
const projectNames = await listAgentProjectDirectoryNames(agentFolderPath);
|
|
30936
|
+
const projectChanges = [];
|
|
30937
|
+
for (const projectName of projectNames) {
|
|
30938
|
+
const projectChange = await commitAgentProjectChangesSafely({
|
|
30939
|
+
projectPath: join(agentFolderPath, AGENT_PROJECTS_DIRECTORY_PATH, projectName),
|
|
30940
|
+
projectName,
|
|
30941
|
+
commitMessage,
|
|
30942
|
+
});
|
|
30943
|
+
if (projectChange) {
|
|
30944
|
+
projectChanges.push(projectChange);
|
|
30945
|
+
}
|
|
30946
|
+
}
|
|
30947
|
+
return projectChanges;
|
|
30948
|
+
}
|
|
30949
|
+
/**
|
|
30950
|
+
* Commits one project without letting its failure reach the answered message.
|
|
30951
|
+
*
|
|
30952
|
+
* @param options - Project identity and commit message.
|
|
30953
|
+
* @returns What was committed, or `null` when nothing changed or committing failed.
|
|
30954
|
+
*
|
|
30955
|
+
* @private helper of `commitAnsweredMessageProjectChanges`
|
|
30956
|
+
*/
|
|
30957
|
+
async function commitAgentProjectChangesSafely(options) {
|
|
30958
|
+
try {
|
|
30959
|
+
return await commitAgentProjectChanges(options);
|
|
30960
|
+
}
|
|
30961
|
+
catch (error) {
|
|
30962
|
+
console.warn(colors.yellow(`Could not commit changes of project "${options.projectName}"`), error);
|
|
30963
|
+
return null;
|
|
30964
|
+
}
|
|
30965
|
+
}
|
|
30966
|
+
|
|
30575
30967
|
/**
|
|
30576
30968
|
* Checks whether one repository-relative path is tracked by Git.
|
|
30577
30969
|
*/
|
|
@@ -30617,7 +31009,7 @@ function buildAgentProjectsPromptSection(options = {}) {
|
|
|
30617
31009
|
|
|
30618
31010
|
- 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.
|
|
30619
31011
|
- 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.
|
|
30620
|
-
-
|
|
31012
|
+
- 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.
|
|
30621
31013
|
- Do not touch anything outside the \`${AGENT_PROJECTS_DIRECTORY_PATH}/\` directory beyond the file changes allowed at the top of this prompt.
|
|
30622
31014
|
|
|
30623
31015
|
${block(buildProjectReferenceInstructions(projectsUrlPath))}
|
|
@@ -30749,13 +31141,79 @@ function formatTimeoutUnit(value, unit) {
|
|
|
30749
31141
|
}
|
|
30750
31142
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
30751
31143
|
|
|
31144
|
+
/**
|
|
31145
|
+
* Describes one planned-message schedule in a single sentence fragment.
|
|
31146
|
+
*
|
|
31147
|
+
* A planned message can repeat forever, repeat a bounded number of times, run inside a date window, or
|
|
31148
|
+
* wake the agent only once. Every surface showing a planned message — the wake-up itself, the goal-chat
|
|
31149
|
+
* notes, the planned-message prompt section, and the model tools — describes it with this one helper,
|
|
31150
|
+
* so an agent never has to reconcile two different wordings of the same plan.
|
|
31151
|
+
*
|
|
31152
|
+
* @param schedule - Schedule of the planned message.
|
|
31153
|
+
* @returns Fragment such as `repeats every 5 minutes (2 of 10 runs done)`.
|
|
31154
|
+
*
|
|
31155
|
+
* @private internal utility of the Agents Server planned messages
|
|
31156
|
+
*/
|
|
31157
|
+
function describeAgentPlannedMessageSchedule(schedule) {
|
|
31158
|
+
const scheduleParts = [
|
|
31159
|
+
describeAgentPlannedMessageRecurrence(schedule),
|
|
31160
|
+
...describeAgentPlannedMessageBounds(schedule),
|
|
31161
|
+
];
|
|
31162
|
+
return scheduleParts.join(', ');
|
|
31163
|
+
}
|
|
31164
|
+
/**
|
|
31165
|
+
* Describes how often one planned message wakes the agent.
|
|
31166
|
+
*
|
|
31167
|
+
* @param schedule - Schedule of the planned message.
|
|
31168
|
+
* @returns Recurrence fragment.
|
|
31169
|
+
*
|
|
31170
|
+
* @private internal utility of `describeAgentPlannedMessageSchedule`
|
|
31171
|
+
*/
|
|
31172
|
+
function describeAgentPlannedMessageRecurrence(schedule) {
|
|
31173
|
+
if (schedule.cronExpression) {
|
|
31174
|
+
return `repeats on cron \`${schedule.cronExpression}\``;
|
|
31175
|
+
}
|
|
31176
|
+
if (schedule.intervalMs) {
|
|
31177
|
+
return `repeats every ${formatTimeoutDurationHuman(schedule.intervalMs)}`;
|
|
31178
|
+
}
|
|
31179
|
+
return schedule.dueAt ? `wakes you once at ${schedule.dueAt}` : 'wakes you once';
|
|
31180
|
+
}
|
|
31181
|
+
/**
|
|
31182
|
+
* Describes the bounds limiting how long one planned message keeps repeating.
|
|
31183
|
+
*
|
|
31184
|
+
* @param schedule - Schedule of the planned message.
|
|
31185
|
+
* @returns Fragments for the starting date, ending date, and run count that are really set.
|
|
31186
|
+
*
|
|
31187
|
+
* @private internal utility of `describeAgentPlannedMessageSchedule`
|
|
31188
|
+
*/
|
|
31189
|
+
function describeAgentPlannedMessageBounds(schedule) {
|
|
31190
|
+
const bounds = [];
|
|
31191
|
+
const runCount = schedule.runCount || 0;
|
|
31192
|
+
if (schedule.startsAt) {
|
|
31193
|
+
bounds.push(`starting ${schedule.startsAt}`);
|
|
31194
|
+
}
|
|
31195
|
+
if (schedule.endsAt) {
|
|
31196
|
+
bounds.push(`until ${schedule.endsAt}`);
|
|
31197
|
+
}
|
|
31198
|
+
if (schedule.maxRunCount) {
|
|
31199
|
+
bounds.push(`${runCount} of ${schedule.maxRunCount} runs done`);
|
|
31200
|
+
}
|
|
31201
|
+
else if (runCount > 0) {
|
|
31202
|
+
bounds.push(`${runCount} run${runCount === 1 ? '' : 's'} done`);
|
|
31203
|
+
}
|
|
31204
|
+
if ((schedule.cronExpression || schedule.intervalMs) && schedule.dueAt) {
|
|
31205
|
+
bounds.push(`next at ${schedule.dueAt}`);
|
|
31206
|
+
}
|
|
31207
|
+
return bounds;
|
|
31208
|
+
}
|
|
31209
|
+
|
|
30752
31210
|
/**
|
|
30753
31211
|
* Builds the planned-message instructions available to an Agents Server-managed coding agent.
|
|
30754
31212
|
*
|
|
30755
31213
|
* Planned messages always target the agent's singleton goal chat, regardless of the chat in which the
|
|
30756
|
-
* wake-up is planned, and
|
|
30757
|
-
* the only channel that changes them, so an answer that merely claims a follow-up
|
|
30758
|
-
* nothing — and an answer that changes nothing keeps the current plan running.
|
|
31214
|
+
* wake-up is planned, and each of them keeps repeating until its schedule is over or it is cancelled.
|
|
31215
|
+
* The sidecar file is the only channel that changes them, so an answer that merely claims a follow-up
|
|
31216
|
+
* was planned changes nothing — and an answer that changes nothing keeps the current plan running.
|
|
30759
31217
|
*
|
|
30760
31218
|
* @param sidecar - Sidecar prepared by the Agents Server for the answered message.
|
|
30761
31219
|
* @returns Prompt section, or an empty string outside Agents Server-managed runs.
|
|
@@ -30767,19 +31225,25 @@ function buildAgentGoalChatPromptSection(sidecar) {
|
|
|
30767
31225
|
return spaceTrim$1((block) => `
|
|
30768
31226
|
## Planned goal-chat messages
|
|
30769
31227
|
|
|
30770
|
-
You can plan a message that
|
|
31228
|
+
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.
|
|
30771
31229
|
|
|
30772
31230
|
${block(buildCurrentPlannedMessagesLines(sidecar.currentPlannedMessages))}
|
|
30773
31231
|
|
|
30774
31232
|
Editing \`${sidecar.relativeSidecarPath}\` is the **only** way to change what wakes you. Writing in your answer that you scheduled something does not schedule anything.
|
|
30775
31233
|
|
|
30776
|
-
- **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
|
|
30777
|
-
- When your goal needs a
|
|
30778
|
-
-
|
|
30779
|
-
|
|
31234
|
+
- **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.
|
|
31235
|
+
- 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.
|
|
31236
|
+
- A planned message is shaped by these fields, which \`set\` and \`update\` both accept:
|
|
31237
|
+
- \`milliseconds\` — repeat interval of at least \`60000\`, or
|
|
31238
|
+
- \`cronExpression\` — a five-field cron such as \`"0 9 * * 1-5"\`, evaluated in the server time zone (use **either** this **or** \`milliseconds\`),
|
|
31239
|
+
- \`maxRunCount\` — how many times in total the message wakes you, for example \`1\` for a one-off message,
|
|
31240
|
+
- \`startsAt\` and \`endsAt\` — ISO dates bounding when it may wake you, for example \`"2026-09-01T08:00:00.000Z"\`.
|
|
31241
|
+
- 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.
|
|
31242
|
+
- When your goal no longer needs a listed message at all, append \`{"action":"cancel","timeoutId":"<timeout id>"}\` without planning a replacement.
|
|
30780
31243
|
- Never edit \`version\`, \`agentPermanentId\`, or \`currentPlannedMessages\`.
|
|
30781
|
-
- The Agents Server applies every command once your answer is finished, and each
|
|
30782
|
-
-
|
|
31244
|
+
- The Agents Server applies every command once your answer is finished, and each wake-up appears in the goal chat and invokes you there.
|
|
31245
|
+
- 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.
|
|
31246
|
+
- 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.
|
|
30783
31247
|
`);
|
|
30784
31248
|
}
|
|
30785
31249
|
/**
|
|
@@ -30812,10 +31276,7 @@ function buildCurrentPlannedMessagesLines(currentPlannedMessages) {
|
|
|
30812
31276
|
function createCurrentPlannedMessageLine(plannedMessage) {
|
|
30813
31277
|
var _a;
|
|
30814
31278
|
const message = ((_a = plannedMessage.message) === null || _a === void 0 ? void 0 : _a.trim()) || 'Continue working towards the current goal.';
|
|
30815
|
-
|
|
30816
|
-
? `repeats every ${formatTimeoutDurationHuman(plannedMessage.intervalMs)}`
|
|
30817
|
-
: `wakes you once at ${plannedMessage.dueAt}`;
|
|
30818
|
-
return `- \`${plannedMessage.timeoutId}\` ${schedule}: ${message}`;
|
|
31279
|
+
return `- \`${plannedMessage.timeoutId}\` ${describeAgentPlannedMessageSchedule(plannedMessage)}: ${message}`;
|
|
30819
31280
|
}
|
|
30820
31281
|
|
|
30821
31282
|
/**
|
|
@@ -37875,7 +38336,7 @@ const AGENT_PLANNED_MESSAGES_DIRECTORY_PATH = join(AGENT_MESSAGES_DIRECTORY_PATH
|
|
|
37875
38336
|
*
|
|
37876
38337
|
* @private internal convention shared by the Agents Server and agent-folder runner
|
|
37877
38338
|
*/
|
|
37878
|
-
const AGENT_PLANNED_MESSAGE_COMMAND_ACTIONS = ['set', 'cancel'];
|
|
38339
|
+
const AGENT_PLANNED_MESSAGE_COMMAND_ACTIONS = ['set', 'update', 'cancel'];
|
|
37879
38340
|
/**
|
|
37880
38341
|
* Creates the relative planned-message sidecar path of one queued message.
|
|
37881
38342
|
*
|
|
@@ -37967,19 +38428,35 @@ function normalizeAgentPlannedMessageSnapshots(rawSnapshots) {
|
|
|
37967
38428
|
* Normalizes the optional fields of one already planned message.
|
|
37968
38429
|
*
|
|
37969
38430
|
* @param snapshot - Planned-message entry with the required identity fields.
|
|
37970
|
-
* @returns Snapshot with a usable
|
|
38431
|
+
* @returns Snapshot with a usable schedule and message.
|
|
37971
38432
|
*
|
|
37972
38433
|
* @private internal utility of `parseAgentPlannedMessagesSidecar`
|
|
37973
38434
|
*/
|
|
37974
38435
|
function createNormalizedAgentPlannedMessageSnapshot(snapshot) {
|
|
37975
|
-
const intervalMs = Number(snapshot.intervalMs);
|
|
37976
38436
|
return {
|
|
37977
38437
|
timeoutId: snapshot.timeoutId,
|
|
37978
38438
|
dueAt: snapshot.dueAt,
|
|
37979
38439
|
message: typeof snapshot.message === 'string' ? snapshot.message : null,
|
|
37980
|
-
intervalMs:
|
|
38440
|
+
intervalMs: normalizeAgentPlannedMessagePositiveCount(snapshot.intervalMs),
|
|
38441
|
+
cronExpression: typeof snapshot.cronExpression === 'string' ? snapshot.cronExpression : null,
|
|
38442
|
+
startsAt: typeof snapshot.startsAt === 'string' ? snapshot.startsAt : null,
|
|
38443
|
+
endsAt: typeof snapshot.endsAt === 'string' ? snapshot.endsAt : null,
|
|
38444
|
+
maxRunCount: normalizeAgentPlannedMessagePositiveCount(snapshot.maxRunCount),
|
|
38445
|
+
runCount: normalizeAgentPlannedMessagePositiveCount(snapshot.runCount) || 0,
|
|
37981
38446
|
};
|
|
37982
38447
|
}
|
|
38448
|
+
/**
|
|
38449
|
+
* Normalizes one optional positive whole number of a planned-message snapshot.
|
|
38450
|
+
*
|
|
38451
|
+
* @param value - Untrusted interval, run count, or run-count limit.
|
|
38452
|
+
* @returns Whole positive number, or `null` when the value cannot be used.
|
|
38453
|
+
*
|
|
38454
|
+
* @private internal utility of `parseAgentPlannedMessagesSidecar`
|
|
38455
|
+
*/
|
|
38456
|
+
function normalizeAgentPlannedMessagePositiveCount(value) {
|
|
38457
|
+
const numericValue = Number(value);
|
|
38458
|
+
return Number.isFinite(numericValue) && numericValue > 0 ? Math.floor(numericValue) : null;
|
|
38459
|
+
}
|
|
37983
38460
|
/**
|
|
37984
38461
|
* Checks whether one untrusted sidecar entry describes an already planned message.
|
|
37985
38462
|
*
|
|
@@ -38205,6 +38682,286 @@ function parseAgentMessageRuntimeLogEvent(line) {
|
|
|
38205
38682
|
}
|
|
38206
38683
|
}
|
|
38207
38684
|
|
|
38685
|
+
/**
|
|
38686
|
+
* Maximum count of external sources reported for one answered message.
|
|
38687
|
+
*
|
|
38688
|
+
* A single answer can reach the same kind of source many times, so the chip row below it stays
|
|
38689
|
+
* readable by keeping only the sources touched first.
|
|
38690
|
+
*
|
|
38691
|
+
* @private internal constant of agent-message touched external sources
|
|
38692
|
+
*/
|
|
38693
|
+
const MAX_TOUCHED_EXTERNAL_SOURCES = 12;
|
|
38694
|
+
/**
|
|
38695
|
+
* Maximum length of one search query shown as the name of a touched search source.
|
|
38696
|
+
*
|
|
38697
|
+
* @private internal constant of agent-message touched external sources
|
|
38698
|
+
*/
|
|
38699
|
+
const MAX_SEARCH_QUERY_LENGTH = 48;
|
|
38700
|
+
/**
|
|
38701
|
+
* Separator between the segments of one integration tool name, as in `mcp__gmail__create_draft`.
|
|
38702
|
+
*
|
|
38703
|
+
* @private internal constant of agent-message touched external sources
|
|
38704
|
+
*/
|
|
38705
|
+
const INTEGRATION_TOOL_NAME_SEPARATOR = '__';
|
|
38706
|
+
/**
|
|
38707
|
+
* First segment marking one tool name as belonging to an integration.
|
|
38708
|
+
*
|
|
38709
|
+
* @private internal constant of agent-message touched external sources
|
|
38710
|
+
*/
|
|
38711
|
+
const INTEGRATION_TOOL_NAME_PREFIX = 'mcp';
|
|
38712
|
+
/**
|
|
38713
|
+
* Names of the harness tools which look something up on the web, indexed for case-insensitive matching.
|
|
38714
|
+
*
|
|
38715
|
+
* @private internal constant of agent-message touched external sources
|
|
38716
|
+
*/
|
|
38717
|
+
const WEB_SEARCH_TOOL_NAMES = new Set(['WebSearch', 'web_search'].map((webSearchToolName) => webSearchToolName.toLowerCase()));
|
|
38718
|
+
/**
|
|
38719
|
+
* Matches one shell command invoking a network client, whose arguments therefore address the outside world.
|
|
38720
|
+
*
|
|
38721
|
+
* @private internal constant of agent-message touched external sources
|
|
38722
|
+
*/
|
|
38723
|
+
const NETWORK_CLIENT_COMMAND_REGEX = /(^|[\s|;&(])(curl|wget|invoke-webrequest|iwr)\b/iu;
|
|
38724
|
+
/**
|
|
38725
|
+
* Matches one web address inside a shell command.
|
|
38726
|
+
*
|
|
38727
|
+
* @private internal constant of agent-message touched external sources
|
|
38728
|
+
*/
|
|
38729
|
+
const COMMAND_URL_REGEX = /https?:\/\/[^\s"'`<>)\]]+/giu;
|
|
38730
|
+
/**
|
|
38731
|
+
* Separators used between the words of one integration name.
|
|
38732
|
+
*
|
|
38733
|
+
* @private internal constant of agent-message touched external sources
|
|
38734
|
+
*/
|
|
38735
|
+
const INTEGRATION_NAME_WORD_SEPARATOR_REGEX = /[-_.\s]+/gu;
|
|
38736
|
+
/**
|
|
38737
|
+
* Hostnames which address the machine the agent runs on and are therefore not external.
|
|
38738
|
+
*
|
|
38739
|
+
* @private internal constant of agent-message touched external sources
|
|
38740
|
+
*/
|
|
38741
|
+
const LOCAL_HOSTNAMES = new Set(['localhost', '127.0.0.1', '0.0.0.0', '::1', '[::1]']);
|
|
38742
|
+
/**
|
|
38743
|
+
* Resolves which sources outside the agent one coding harness touched while answering a single message.
|
|
38744
|
+
*
|
|
38745
|
+
* The runtime log streams what the harness really did, so a source counts as touched when the
|
|
38746
|
+
* harness reached it in a tool invocation — calling an integration, fetching a web address,
|
|
38747
|
+
* searching the web, or running a network client in the shell. Only tool payloads are inspected:
|
|
38748
|
+
* tool results and assistant narration are ignored so a service merely mentioned in the
|
|
38749
|
+
* conversation is never reported, and addresses of the machine the agent runs on are dropped
|
|
38750
|
+
* because they are internal.
|
|
38751
|
+
*
|
|
38752
|
+
* @param options - Raw runtime log content of one answered message.
|
|
38753
|
+
* @returns Touched external sources without duplicates, ordered by first appearance.
|
|
38754
|
+
* @private internal utility of the agent-message runtime
|
|
38755
|
+
*/
|
|
38756
|
+
function resolveAgentMessageTouchedExternalSources(options) {
|
|
38757
|
+
const touchedExternalSources = new Map();
|
|
38758
|
+
for (const event of parseAgentMessageRuntimeLogEvents(options.logText)) {
|
|
38759
|
+
for (const externalSource of resolveRuntimeLogEventExternalSources(event)) {
|
|
38760
|
+
const externalSourceKey = createExternalSourceKey(externalSource);
|
|
38761
|
+
if (!touchedExternalSources.has(externalSourceKey)) {
|
|
38762
|
+
touchedExternalSources.set(externalSourceKey, externalSource);
|
|
38763
|
+
}
|
|
38764
|
+
if (touchedExternalSources.size === MAX_TOUCHED_EXTERNAL_SOURCES) {
|
|
38765
|
+
return Array.from(touchedExternalSources.values());
|
|
38766
|
+
}
|
|
38767
|
+
}
|
|
38768
|
+
}
|
|
38769
|
+
return Array.from(touchedExternalSources.values());
|
|
38770
|
+
}
|
|
38771
|
+
/**
|
|
38772
|
+
* Collects every external source described by one runtime log event.
|
|
38773
|
+
*
|
|
38774
|
+
* Claude Code reports tool invocations as `tool_use` content blocks, while Codex reports executed
|
|
38775
|
+
* commands, web searches, and integration calls as items.
|
|
38776
|
+
*
|
|
38777
|
+
* @param event - One structured runtime log event.
|
|
38778
|
+
* @returns External sources the event reached, possibly with duplicates.
|
|
38779
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38780
|
+
*/
|
|
38781
|
+
function resolveRuntimeLogEventExternalSources(event) {
|
|
38782
|
+
var _a;
|
|
38783
|
+
const externalSources = [];
|
|
38784
|
+
for (const contentBlock of ((_a = event.message) === null || _a === void 0 ? void 0 : _a.content) || []) {
|
|
38785
|
+
if (contentBlock.type === 'tool_use') {
|
|
38786
|
+
externalSources.push(...resolveToolUseExternalSources(contentBlock));
|
|
38787
|
+
}
|
|
38788
|
+
}
|
|
38789
|
+
externalSources.push(...resolveCodexItemExternalSources(event.item));
|
|
38790
|
+
return externalSources;
|
|
38791
|
+
}
|
|
38792
|
+
/**
|
|
38793
|
+
* Collects the external sources reached by one Claude Code tool invocation.
|
|
38794
|
+
*
|
|
38795
|
+
* @param contentBlock - One `tool_use` content block.
|
|
38796
|
+
* @returns External sources the invocation reached.
|
|
38797
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38798
|
+
*/
|
|
38799
|
+
function resolveToolUseExternalSources(contentBlock) {
|
|
38800
|
+
const toolName = contentBlock.name || '';
|
|
38801
|
+
const toolInput = contentBlock.input || {};
|
|
38802
|
+
return collectDefinedExternalSources([
|
|
38803
|
+
createIntegrationExternalSource(resolveIntegrationName(toolName)),
|
|
38804
|
+
typeof toolInput.url === 'string' ? createWebsiteExternalSource(toolInput.url) : null,
|
|
38805
|
+
WEB_SEARCH_TOOL_NAMES.has(toolName.toLowerCase()) && typeof toolInput.query === 'string'
|
|
38806
|
+
? createSearchExternalSource(toolInput.query)
|
|
38807
|
+
: null,
|
|
38808
|
+
...(typeof toolInput.command === 'string' ? resolveNetworkCommandExternalSources(toolInput.command) : []),
|
|
38809
|
+
]);
|
|
38810
|
+
}
|
|
38811
|
+
/**
|
|
38812
|
+
* Collects the external sources reached by one Codex runtime item.
|
|
38813
|
+
*
|
|
38814
|
+
* @param item - One Codex item of a runtime log event.
|
|
38815
|
+
* @returns External sources the item reached.
|
|
38816
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38817
|
+
*/
|
|
38818
|
+
function resolveCodexItemExternalSources(item) {
|
|
38819
|
+
if (!item) {
|
|
38820
|
+
return [];
|
|
38821
|
+
}
|
|
38822
|
+
return collectDefinedExternalSources([
|
|
38823
|
+
item.type === 'mcp_tool_call'
|
|
38824
|
+
? createIntegrationExternalSource(item.server || resolveIntegrationName(item.tool || ''))
|
|
38825
|
+
: null,
|
|
38826
|
+
item.type === 'web_search' && typeof item.query === 'string' ? createSearchExternalSource(item.query) : null,
|
|
38827
|
+
...(typeof item.command === 'string' ? resolveNetworkCommandExternalSources(item.command) : []),
|
|
38828
|
+
]);
|
|
38829
|
+
}
|
|
38830
|
+
/**
|
|
38831
|
+
* Drops the candidates which turned out not to describe an external source.
|
|
38832
|
+
*
|
|
38833
|
+
* @param candidates - Resolved sources mixed with the candidates that resolved to nothing.
|
|
38834
|
+
* @returns Only the sources which were resolved.
|
|
38835
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38836
|
+
*/
|
|
38837
|
+
function collectDefinedExternalSources(candidates) {
|
|
38838
|
+
return candidates.filter((candidate) => candidate !== null);
|
|
38839
|
+
}
|
|
38840
|
+
/**
|
|
38841
|
+
* Resolves the integration a tool name belongs to, following the `mcp__<integration>__<tool>` convention.
|
|
38842
|
+
*
|
|
38843
|
+
* @param toolName - Raw harness tool name.
|
|
38844
|
+
* @returns Raw integration name, or `null` when the tool belongs to no integration.
|
|
38845
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38846
|
+
*/
|
|
38847
|
+
function resolveIntegrationName(toolName) {
|
|
38848
|
+
const toolNameSegments = toolName.split(INTEGRATION_TOOL_NAME_SEPARATOR);
|
|
38849
|
+
if (toolNameSegments.length < 3 || toolNameSegments[0].toLowerCase() !== INTEGRATION_TOOL_NAME_PREFIX) {
|
|
38850
|
+
return null;
|
|
38851
|
+
}
|
|
38852
|
+
return toolNameSegments[1] || null;
|
|
38853
|
+
}
|
|
38854
|
+
/**
|
|
38855
|
+
* Creates one touched integration source.
|
|
38856
|
+
*
|
|
38857
|
+
* @param integrationName - Raw integration name, or `null` when there is none.
|
|
38858
|
+
* @returns Touched source, or `null` when the integration cannot be named.
|
|
38859
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38860
|
+
*/
|
|
38861
|
+
function createIntegrationExternalSource(integrationName) {
|
|
38862
|
+
const humanizedIntegrationName = humanizeIntegrationName(integrationName || '');
|
|
38863
|
+
if (humanizedIntegrationName === '') {
|
|
38864
|
+
return null;
|
|
38865
|
+
}
|
|
38866
|
+
return { kind: 'integration', name: humanizedIntegrationName };
|
|
38867
|
+
}
|
|
38868
|
+
/**
|
|
38869
|
+
* Creates one touched website source.
|
|
38870
|
+
*
|
|
38871
|
+
* @param rawUrl - Raw web address the harness reached.
|
|
38872
|
+
* @returns Touched source, or `null` when the address is unusable or addresses the local machine.
|
|
38873
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38874
|
+
*/
|
|
38875
|
+
function createWebsiteExternalSource(rawUrl) {
|
|
38876
|
+
let url;
|
|
38877
|
+
try {
|
|
38878
|
+
url = new URL(rawUrl.trim());
|
|
38879
|
+
}
|
|
38880
|
+
catch (_a) {
|
|
38881
|
+
return null;
|
|
38882
|
+
}
|
|
38883
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
38884
|
+
return null;
|
|
38885
|
+
}
|
|
38886
|
+
const hostname = url.hostname.toLowerCase();
|
|
38887
|
+
if (hostname === '' || LOCAL_HOSTNAMES.has(hostname) || hostname.endsWith('.localhost')) {
|
|
38888
|
+
return null;
|
|
38889
|
+
}
|
|
38890
|
+
return { kind: 'website', name: hostname, url: url.href };
|
|
38891
|
+
}
|
|
38892
|
+
/**
|
|
38893
|
+
* Creates one touched web search source.
|
|
38894
|
+
*
|
|
38895
|
+
* @param query - Raw query the harness looked up.
|
|
38896
|
+
* @returns Touched source, or `null` when the query is empty.
|
|
38897
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38898
|
+
*/
|
|
38899
|
+
function createSearchExternalSource(query) {
|
|
38900
|
+
const normalizedQuery = query.replace(/\s+/gu, ' ').trim();
|
|
38901
|
+
if (normalizedQuery === '') {
|
|
38902
|
+
return null;
|
|
38903
|
+
}
|
|
38904
|
+
return {
|
|
38905
|
+
kind: 'search',
|
|
38906
|
+
name: normalizedQuery.length <= MAX_SEARCH_QUERY_LENGTH
|
|
38907
|
+
? normalizedQuery
|
|
38908
|
+
: `${normalizedQuery.slice(0, MAX_SEARCH_QUERY_LENGTH).trimEnd()}…`,
|
|
38909
|
+
};
|
|
38910
|
+
}
|
|
38911
|
+
/**
|
|
38912
|
+
* Collects the websites addressed by one shell command running a network client.
|
|
38913
|
+
*
|
|
38914
|
+
* Commands which do not invoke a network client are ignored, so a web address that merely appears
|
|
38915
|
+
* in the text the agent writes into a file is never reported as touched.
|
|
38916
|
+
*
|
|
38917
|
+
* @param command - One executed shell command.
|
|
38918
|
+
* @returns Touched website sources of the command.
|
|
38919
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38920
|
+
*/
|
|
38921
|
+
function resolveNetworkCommandExternalSources(command) {
|
|
38922
|
+
if (!NETWORK_CLIENT_COMMAND_REGEX.test(command)) {
|
|
38923
|
+
return [];
|
|
38924
|
+
}
|
|
38925
|
+
const commandUrlRegex = new RegExp(COMMAND_URL_REGEX.source, COMMAND_URL_REGEX.flags);
|
|
38926
|
+
const externalSources = [];
|
|
38927
|
+
let commandUrlMatch = commandUrlRegex.exec(command);
|
|
38928
|
+
while (commandUrlMatch !== null) {
|
|
38929
|
+
const externalSource = createWebsiteExternalSource(commandUrlMatch[0]);
|
|
38930
|
+
if (externalSource) {
|
|
38931
|
+
externalSources.push(externalSource);
|
|
38932
|
+
}
|
|
38933
|
+
commandUrlMatch = commandUrlRegex.exec(command);
|
|
38934
|
+
}
|
|
38935
|
+
return externalSources;
|
|
38936
|
+
}
|
|
38937
|
+
/**
|
|
38938
|
+
* Converts one raw integration name into its user-facing form.
|
|
38939
|
+
*
|
|
38940
|
+
* For example `google-calendar` becomes `Google Calendar`.
|
|
38941
|
+
*
|
|
38942
|
+
* @param integrationName - Raw integration name.
|
|
38943
|
+
* @returns Human-readable integration name, or an empty string when there is nothing to show.
|
|
38944
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38945
|
+
*/
|
|
38946
|
+
function humanizeIntegrationName(integrationName) {
|
|
38947
|
+
return integrationName
|
|
38948
|
+
.trim()
|
|
38949
|
+
.split(INTEGRATION_NAME_WORD_SEPARATOR_REGEX)
|
|
38950
|
+
.filter((integrationNameWord) => integrationNameWord !== '')
|
|
38951
|
+
.map((integrationNameWord) => capitalize(integrationNameWord))
|
|
38952
|
+
.join(' ');
|
|
38953
|
+
}
|
|
38954
|
+
/**
|
|
38955
|
+
* Builds the key identifying one external source across the whole run.
|
|
38956
|
+
*
|
|
38957
|
+
* @param externalSource - One touched external source.
|
|
38958
|
+
* @returns Key under which repeated touches of the same source collapse into one.
|
|
38959
|
+
* @private internal helper of `resolveAgentMessageTouchedExternalSources`
|
|
38960
|
+
*/
|
|
38961
|
+
function createExternalSourceKey(externalSource) {
|
|
38962
|
+
return `${externalSource.kind}:${externalSource.name.toLowerCase()}`;
|
|
38963
|
+
}
|
|
38964
|
+
|
|
38208
38965
|
/**
|
|
38209
38966
|
* Matches one project directory name following the agent `projects/` folder in a file path or command.
|
|
38210
38967
|
*
|
|
@@ -38329,43 +39086,25 @@ function resolveCandidateProjectNames(toolInvocationText) {
|
|
|
38329
39086
|
}
|
|
38330
39087
|
|
|
38331
39088
|
/**
|
|
38332
|
-
* Resolves which agent projects one answered message
|
|
39089
|
+
* Resolves which agent projects and which external sources one answered message touched.
|
|
38333
39090
|
*
|
|
38334
39091
|
* The runtime log is deleted as soon as the harness run finishes, so this must be called while
|
|
38335
|
-
* the log still exists — the Agents Server later shows
|
|
38336
|
-
* answer. Reporting
|
|
38337
|
-
*
|
|
39092
|
+
* the log still exists — the Agents Server later shows everything reported here as chips below
|
|
39093
|
+
* the answer. Reporting touches is best-effort telemetry: an unreadable log or projects folder
|
|
39094
|
+
* simply yields nothing instead of failing the already answered message.
|
|
38338
39095
|
*
|
|
38339
39096
|
* @param options - Agent folder path and the live runtime log path of the answered message.
|
|
38340
|
-
* @returns Touched
|
|
39097
|
+
* @returns Touched projects and external sources, ordered by first appearance in the run.
|
|
38341
39098
|
*/
|
|
38342
|
-
async function
|
|
39099
|
+
async function resolveAnsweredMessageTouches(options) {
|
|
38343
39100
|
const [logText, knownProjectNames] = await Promise.all([
|
|
38344
39101
|
readOptionalTextFile(options.runtimeLogPath),
|
|
38345
39102
|
listAgentProjectDirectoryNames(options.projectPath),
|
|
38346
39103
|
]);
|
|
38347
|
-
return
|
|
38348
|
-
}
|
|
38349
|
-
|
|
38350
|
-
|
|
38351
|
-
*
|
|
38352
|
-
* @param projectPath - Absolute path of the local agent folder.
|
|
38353
|
-
* @returns Project directory names, or an empty list when the agent has no projects folder.
|
|
38354
|
-
*
|
|
38355
|
-
* @private helper of `resolveTouchedAgentProjects`
|
|
38356
|
-
*/
|
|
38357
|
-
async function listAgentProjectDirectoryNames(projectPath) {
|
|
38358
|
-
try {
|
|
38359
|
-
const projectsRootEntries = await readdir(join(projectPath, AGENT_PROJECTS_DIRECTORY_PATH), {
|
|
38360
|
-
withFileTypes: true,
|
|
38361
|
-
});
|
|
38362
|
-
return projectsRootEntries
|
|
38363
|
-
.filter((projectsRootEntry) => projectsRootEntry.isDirectory())
|
|
38364
|
-
.map((projectDirectoryEntry) => projectDirectoryEntry.name);
|
|
38365
|
-
}
|
|
38366
|
-
catch (_a) {
|
|
38367
|
-
return [];
|
|
38368
|
-
}
|
|
39104
|
+
return {
|
|
39105
|
+
touchedProjectNames: resolveAgentMessageTouchedProjectNames({ logText, knownProjectNames }),
|
|
39106
|
+
touchedExternalSources: resolveAgentMessageTouchedExternalSources({ logText }),
|
|
39107
|
+
};
|
|
38369
39108
|
}
|
|
38370
39109
|
/**
|
|
38371
39110
|
* Reads one text file and treats a missing runtime log as "nothing was recorded".
|
|
@@ -38373,7 +39112,7 @@ async function listAgentProjectDirectoryNames(projectPath) {
|
|
|
38373
39112
|
* @param filePath - Absolute path of the file to read.
|
|
38374
39113
|
* @returns File content, or `null` when it cannot be read.
|
|
38375
39114
|
*
|
|
38376
|
-
* @private helper of `
|
|
39115
|
+
* @private helper of `resolveAnsweredMessageTouches`
|
|
38377
39116
|
*/
|
|
38378
39117
|
async function readOptionalTextFile(filePath) {
|
|
38379
39118
|
try {
|
|
@@ -38690,7 +39429,7 @@ async function runQueuedAgentMessage(options) {
|
|
|
38690
39429
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
38691
39430
|
const executionStartedAt = new Date().toISOString();
|
|
38692
39431
|
let promptRunResult;
|
|
38693
|
-
let
|
|
39432
|
+
let answeredMessageTouches = { touchedProjectNames: [], touchedExternalSources: [] };
|
|
38694
39433
|
try {
|
|
38695
39434
|
try {
|
|
38696
39435
|
promptRunResult = await withPromptRuntimeLog(scriptPath, async (logPath) => {
|
|
@@ -38706,9 +39445,12 @@ async function runQueuedAgentMessage(options) {
|
|
|
38706
39445
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(attemptCount);
|
|
38707
39446
|
},
|
|
38708
39447
|
});
|
|
38709
|
-
// Note: The runtime log is deleted right after this handler, so
|
|
39448
|
+
// Note: The runtime log is deleted right after this handler, so everything this
|
|
38710
39449
|
// answer worked with must be resolved while the log still exists.
|
|
38711
|
-
|
|
39450
|
+
answeredMessageTouches = await resolveAnsweredMessageTouches({
|
|
39451
|
+
projectPath,
|
|
39452
|
+
runtimeLogPath: logPath,
|
|
39453
|
+
});
|
|
38712
39454
|
return runResult;
|
|
38713
39455
|
}, { preserveArtifactsOnSuccess: false });
|
|
38714
39456
|
}
|
|
@@ -38726,6 +39468,12 @@ async function runQueuedAgentMessage(options) {
|
|
|
38726
39468
|
}
|
|
38727
39469
|
const executionFinishedAt = new Date().toISOString();
|
|
38728
39470
|
await normalizeLineEndingsForAgentRound(projectPath, runOptions, roundChangedFilesSnapshot);
|
|
39471
|
+
// Note: Every agent project keeps its own git history, so what this message did to a project is
|
|
39472
|
+
// committed there before the answer becomes visible and travels with the run report.
|
|
39473
|
+
const projectChanges = await commitAnsweredMessageProjectChanges({
|
|
39474
|
+
agentFolderPath: projectPath,
|
|
39475
|
+
commitMessage: buildAgentMessageCommitMessage(queuedMessage),
|
|
39476
|
+
});
|
|
38729
39477
|
const finishedTeamWorkspace = await finalizeAgentTeamConversationWorkspace({
|
|
38730
39478
|
projectPath,
|
|
38731
39479
|
queuedMessage,
|
|
@@ -38747,7 +39495,13 @@ async function runQueuedAgentMessage(options) {
|
|
|
38747
39495
|
startedAt: executionStartedAt,
|
|
38748
39496
|
finishedAt: executionFinishedAt,
|
|
38749
39497
|
},
|
|
38750
|
-
...(touchedProjectNames.length === 0
|
|
39498
|
+
...(answeredMessageTouches.touchedProjectNames.length === 0
|
|
39499
|
+
? {}
|
|
39500
|
+
: { touchedProjectNames: answeredMessageTouches.touchedProjectNames }),
|
|
39501
|
+
...(answeredMessageTouches.touchedExternalSources.length === 0
|
|
39502
|
+
? {}
|
|
39503
|
+
: { touchedExternalSources: answeredMessageTouches.touchedExternalSources }),
|
|
39504
|
+
...(projectChanges.length === 0 ? {} : { projectChanges }),
|
|
38751
39505
|
},
|
|
38752
39506
|
});
|
|
38753
39507
|
await commitAnsweredMessageIfEnabled({
|
|
@@ -41763,7 +42517,9 @@ function comparePrereleaseIdentifier(firstIdentifier, secondIdentifier) {
|
|
|
41763
42517
|
async function $checkHarnessInstallation(definition, isHarnessUpdateCheckEnabled = true) {
|
|
41764
42518
|
const [installedVersion, latestVersion] = await Promise.all([
|
|
41765
42519
|
$resolveInstalledHarnessVersion(definition),
|
|
41766
|
-
isHarnessUpdateCheckEnabled
|
|
42520
|
+
isHarnessUpdateCheckEnabled
|
|
42521
|
+
? $resolveLatestNpmPackageVersion(definition.npmPackageName)
|
|
42522
|
+
: Promise.resolve(null),
|
|
41767
42523
|
]);
|
|
41768
42524
|
return {
|
|
41769
42525
|
definition,
|
|
@@ -42447,6 +43203,52 @@ function listDefaultCoderProjectPromptTemplateDisplayPaths() {
|
|
|
42447
43203
|
// Note: [🟡] Code for CLI command [init](src/cli/cli-commands/coder/init.ts) should never be published outside of `@promptbook/cli`
|
|
42448
43204
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
42449
43205
|
|
|
43206
|
+
/**
|
|
43207
|
+
* Default wait duration applied before retrying a prompt round after an error (10 minutes).
|
|
43208
|
+
*
|
|
43209
|
+
* @private internal constant of `ptbk coder` wait handling
|
|
43210
|
+
*/
|
|
43211
|
+
const DEFAULT_WAIT_AFTER_ERROR_MS$1 = 10 * 60 * 1000;
|
|
43212
|
+
/**
|
|
43213
|
+
* Parses an optional Commander duration string and returns the resolved milliseconds.
|
|
43214
|
+
*
|
|
43215
|
+
* Returns `defaultMs` when the flag was not provided or was provided without a non-empty value.
|
|
43216
|
+
*
|
|
43217
|
+
* @private internal utility of `ptbk coder` wait handling
|
|
43218
|
+
*/
|
|
43219
|
+
function parseOptionalWaitDuration(value, defaultMs) {
|
|
43220
|
+
if (typeof value !== 'string' || value === '') {
|
|
43221
|
+
return defaultMs;
|
|
43222
|
+
}
|
|
43223
|
+
return parseDuration(value);
|
|
43224
|
+
}
|
|
43225
|
+
/**
|
|
43226
|
+
* Parses an optional Commander period duration string and returns the resolved milliseconds.
|
|
43227
|
+
*
|
|
43228
|
+
* Returns `undefined` when the flag was not provided or was provided without a non-empty value,
|
|
43229
|
+
* which means the command runs only once instead of repeating itself.
|
|
43230
|
+
*
|
|
43231
|
+
* @throws {NotAllowed} When the duration is not a positive one, because a non-positive period
|
|
43232
|
+
* would repeat the command without ever pausing between two rounds
|
|
43233
|
+
*
|
|
43234
|
+
* @private internal utility of `ptbk coder` wait handling
|
|
43235
|
+
*/
|
|
43236
|
+
function parseOptionalPeriodDuration(optionName, value) {
|
|
43237
|
+
if (typeof value !== 'string' || value === '') {
|
|
43238
|
+
return undefined;
|
|
43239
|
+
}
|
|
43240
|
+
const periodMs = parseDuration(value);
|
|
43241
|
+
if (periodMs <= 0) {
|
|
43242
|
+
throw new NotAllowed(spaceTrim$1(`
|
|
43243
|
+
Invalid value for \`${optionName}\`: \`${value}\`.
|
|
43244
|
+
|
|
43245
|
+
Use a **positive** duration like \`5h\`, \`30m\` or \`1h30m\`.
|
|
43246
|
+
`));
|
|
43247
|
+
}
|
|
43248
|
+
return periodMs;
|
|
43249
|
+
}
|
|
43250
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
43251
|
+
|
|
42450
43252
|
/**
|
|
42451
43253
|
* Initializes `coder ping` command for Promptbook CLI utilities
|
|
42452
43254
|
*
|
|
@@ -42465,6 +43267,7 @@ function $initializeCoderPingCommand(program) {
|
|
|
42465
43267
|
- Verifies that the selected harness, model, thinking level and authentication really work
|
|
42466
43268
|
- Reports the answer of the harness, the response time and the reported usage
|
|
42467
43269
|
- Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
|
|
43270
|
+
- Optional --period keeps the quota window refreshing by pinging once per period until stopped
|
|
42468
43271
|
- Leaves the project exactly as it was — nothing is read, written, changed or committed
|
|
42469
43272
|
- Checks that the selected harness is installed globally and up to date unless --no-harness-update is used
|
|
42470
43273
|
- Use --no-ui to stream the raw harness output instead of only the compact result
|
|
@@ -42472,21 +43275,34 @@ function $initializeCoderPingCommand(program) {
|
|
|
42472
43275
|
addPromptRunnerSelectionOptions(command);
|
|
42473
43276
|
addHarnessUpdateOption(command);
|
|
42474
43277
|
addPromptRunnerRuntimeOptions(command);
|
|
43278
|
+
command.option('--period <duration>', spaceTrim$1(`
|
|
43279
|
+
Keep pinging once per period instead of pinging only once.
|
|
43280
|
+
Accepts durations like 5h, 30m, 1h30m and repeats until it is stopped with CTRL+C.
|
|
43281
|
+
`));
|
|
42475
43282
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
43283
|
+
const { period: periodValue } = cliOptions;
|
|
42476
43284
|
const runnerOptions = normalizePromptRunnerSelectionCliOptions(cliOptions, { isAgentRequired: true });
|
|
42477
43285
|
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
43286
|
+
// Note: The period is validated before the harness installation check, so a mistyped duration fails fast
|
|
43287
|
+
const periodMs = parseOptionalPeriodDuration('--period', periodValue);
|
|
42478
43288
|
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
42479
|
-
|
|
42480
|
-
const { pingCoderHarness } = await Promise.resolve().then(function () { return pingCoderHarness$1; });
|
|
42481
|
-
const { printCoderPingResult } = await Promise.resolve().then(function () { return printCoderPingResult$1; });
|
|
42482
|
-
const result = await pingCoderHarness({
|
|
43289
|
+
const pingOptions = {
|
|
42483
43290
|
agentName: runnerOptions.agentName,
|
|
42484
43291
|
model: runnerOptions.model,
|
|
42485
43292
|
thinkingLevel: runnerOptions.thinkingLevel,
|
|
42486
43293
|
allowCredits: runnerOptions.allowCredits,
|
|
42487
43294
|
shouldPrintLiveOutput: runnerOptions.noUi,
|
|
42488
|
-
}
|
|
42489
|
-
|
|
43295
|
+
};
|
|
43296
|
+
// Note: Import the ping dynamically to avoid loading heavy dependencies until needed
|
|
43297
|
+
if (periodMs !== undefined) {
|
|
43298
|
+
const { pingCoderHarnessPeriodically } = await Promise.resolve().then(function () { return pingCoderHarnessPeriodically$1; });
|
|
43299
|
+
// Note: This never returns - it keeps pinging until the user stops the process
|
|
43300
|
+
await pingCoderHarnessPeriodically({ ...pingOptions, periodMs });
|
|
43301
|
+
return;
|
|
43302
|
+
}
|
|
43303
|
+
const { pingCoderHarness } = await Promise.resolve().then(function () { return pingCoderHarness$1; });
|
|
43304
|
+
const { printCoderPingResult } = await Promise.resolve().then(function () { return printCoderPingResult$1; });
|
|
43305
|
+
printCoderPingResult(await pingCoderHarness(pingOptions));
|
|
42490
43306
|
}));
|
|
42491
43307
|
}
|
|
42492
43308
|
// Note: [🟡] Code for CLI command [ping](src/cli/cli-commands/coder/ping.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -42923,27 +43739,6 @@ function isTestBeforeMode(value) {
|
|
|
42923
43739
|
return TEST_BEFORE_MODE_VALUES.includes(value);
|
|
42924
43740
|
}
|
|
42925
43741
|
|
|
42926
|
-
/**
|
|
42927
|
-
* Default wait duration applied before retrying a prompt round after an error (10 minutes).
|
|
42928
|
-
*
|
|
42929
|
-
* @private internal constant of `ptbk coder` wait handling
|
|
42930
|
-
*/
|
|
42931
|
-
const DEFAULT_WAIT_AFTER_ERROR_MS$1 = 10 * 60 * 1000;
|
|
42932
|
-
/**
|
|
42933
|
-
* Parses an optional Commander duration string and returns the resolved milliseconds.
|
|
42934
|
-
*
|
|
42935
|
-
* Returns `defaultMs` when the flag was not provided or was provided without a non-empty value.
|
|
42936
|
-
*
|
|
42937
|
-
* @private internal utility of `ptbk coder` wait handling
|
|
42938
|
-
*/
|
|
42939
|
-
function parseOptionalWaitDuration(value, defaultMs) {
|
|
42940
|
-
if (typeof value !== 'string' || value === '') {
|
|
42941
|
-
return defaultMs;
|
|
42942
|
-
}
|
|
42943
|
-
return parseDuration(value);
|
|
42944
|
-
}
|
|
42945
|
-
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
42946
|
-
|
|
42947
43742
|
/**
|
|
42948
43743
|
* Initializes `coder run` command for Promptbook CLI utilities
|
|
42949
43744
|
*
|
|
@@ -66985,7 +67780,7 @@ function validateBook(source) {
|
|
|
66985
67780
|
padBook(validateBook(spaceTrim$1(`
|
|
66986
67781
|
AI Avatar
|
|
66987
67782
|
|
|
66988
|
-
|
|
67783
|
+
GOAL Help users with their tasks as a friendly AI assistant.
|
|
66989
67784
|
`)));
|
|
66990
67785
|
// <- Note: Not using book`...` notation to avoid strange error in jest unit tests `TypeError: (0 , book_notation_1.book) is not a function`
|
|
66991
67786
|
// <- TODO: [🐱🚀] `GENESIS_BOOK` / `ADAM_BOOK` in `/agents/adam.book`
|
|
@@ -72682,6 +73477,23 @@ var findUnwrittenPrompts$1 = /*#__PURE__*/Object.freeze({
|
|
|
72682
73477
|
findUnwrittenPrompts: findUnwrittenPrompts
|
|
72683
73478
|
});
|
|
72684
73479
|
|
|
73480
|
+
/**
|
|
73481
|
+
* Formats one unknown error-like value into its readable message without the stack trace.
|
|
73482
|
+
*
|
|
73483
|
+
* Use this instead of `formatUnknownErrorDetails` whenever the text is shown to the user, for example
|
|
73484
|
+
* inside a branded error, where the stack of the wrapped error would only bury the actual cause.
|
|
73485
|
+
*/
|
|
73486
|
+
function formatUnknownErrorMessage(error) {
|
|
73487
|
+
if (error instanceof Error) {
|
|
73488
|
+
return error.message;
|
|
73489
|
+
}
|
|
73490
|
+
if (typeof error === 'string') {
|
|
73491
|
+
return error;
|
|
73492
|
+
}
|
|
73493
|
+
const serializedError = JSON.stringify(error, null, 2);
|
|
73494
|
+
return serializedError !== null && serializedError !== void 0 ? serializedError : String(error);
|
|
73495
|
+
}
|
|
73496
|
+
|
|
72685
73497
|
/**
|
|
72686
73498
|
* Builds a normalized temporary shell script path for prompt runners.
|
|
72687
73499
|
*/
|
|
@@ -72919,6 +73731,60 @@ var printCoderPingResult$1 = /*#__PURE__*/Object.freeze({
|
|
|
72919
73731
|
printCoderPingResult: printCoderPingResult
|
|
72920
73732
|
});
|
|
72921
73733
|
|
|
73734
|
+
/**
|
|
73735
|
+
* How often the countdown to the next periodic ping is reported to the console (30 minutes).
|
|
73736
|
+
*
|
|
73737
|
+
* A period like `5h` is meant to be left running unattended, so the countdown is deliberately
|
|
73738
|
+
* coarse — it is a sign of life, not a progress bar.
|
|
73739
|
+
*/
|
|
73740
|
+
const CODER_PING_COUNTDOWN_UPDATE_INTERVAL_MS = 30 * 60 * 1000;
|
|
73741
|
+
/**
|
|
73742
|
+
* Pings the selected harness and model once per period until the process is stopped.
|
|
73743
|
+
*
|
|
73744
|
+
* This keeps the quota window of the harness refreshing without any real work, so the window is
|
|
73745
|
+
* always open by the time you need it. The loop never ends on its own — it is stopped with `CTRL+C`
|
|
73746
|
+
* or by killing the process — therefore a failing ping is reported and the next period is started
|
|
73747
|
+
* instead of tearing the whole loop down.
|
|
73748
|
+
*/
|
|
73749
|
+
async function pingCoderHarnessPeriodically(options) {
|
|
73750
|
+
const { periodMs, ...pingOptions } = options;
|
|
73751
|
+
console.info(colors.gray(`🏓 Pinging every ${formatDurationMs(periodMs)} until stopped with CTRL+C`));
|
|
73752
|
+
// Note: The loop is intentionally endless - only `CTRL+C` or killing the process ends it
|
|
73753
|
+
for (;;) {
|
|
73754
|
+
const nextPingTimeMs = Date.now() + periodMs;
|
|
73755
|
+
await reportOneCoderPing(pingOptions);
|
|
73756
|
+
await waitUntilNextCoderPing(nextPingTimeMs);
|
|
73757
|
+
}
|
|
73758
|
+
}
|
|
73759
|
+
/**
|
|
73760
|
+
* Sends and reports one ping of the endless loop, keeping the loop alive when the harness fails.
|
|
73761
|
+
*/
|
|
73762
|
+
async function reportOneCoderPing(options) {
|
|
73763
|
+
try {
|
|
73764
|
+
printCoderPingResult(await pingCoderHarness(options));
|
|
73765
|
+
}
|
|
73766
|
+
catch (error) {
|
|
73767
|
+
console.error(colors.red(`🏓 Ping failed: ${formatUnknownErrorMessage(error)}`));
|
|
73768
|
+
}
|
|
73769
|
+
}
|
|
73770
|
+
/**
|
|
73771
|
+
* Waits until the wall-clock time of the next ping, reporting how much of the period is left.
|
|
73772
|
+
*/
|
|
73773
|
+
async function waitUntilNextCoderPing(nextPingTimeMs) {
|
|
73774
|
+
await waitUntilWorldTimeDeadline({
|
|
73775
|
+
deadlineTimeMs: nextPingTimeMs,
|
|
73776
|
+
pollIntervalMs: CODER_PING_COUNTDOWN_UPDATE_INTERVAL_MS,
|
|
73777
|
+
onTick(remainingDurationMs) {
|
|
73778
|
+
console.info(colors.gray(` Next ping in ${formatDurationMs(remainingDurationMs)}`));
|
|
73779
|
+
},
|
|
73780
|
+
});
|
|
73781
|
+
}
|
|
73782
|
+
|
|
73783
|
+
var pingCoderHarnessPeriodically$1 = /*#__PURE__*/Object.freeze({
|
|
73784
|
+
__proto__: null,
|
|
73785
|
+
pingCoderHarnessPeriodically: pingCoderHarnessPeriodically
|
|
73786
|
+
});
|
|
73787
|
+
|
|
72922
73788
|
/**
|
|
72923
73789
|
* Default wait duration applied before retrying a failed prompt round.
|
|
72924
73790
|
*/
|
|
@@ -75752,23 +76618,6 @@ function buildCoderIsolationWorktreeDisplayPath(taskName) {
|
|
|
75752
76618
|
return getPromptbookTemporaryPath(CODER_ISOLATION_WORKTREES_DIRECTORY_NAME, taskName);
|
|
75753
76619
|
}
|
|
75754
76620
|
|
|
75755
|
-
/**
|
|
75756
|
-
* Formats one unknown error-like value into its readable message without the stack trace.
|
|
75757
|
-
*
|
|
75758
|
-
* Use this instead of `formatUnknownErrorDetails` whenever the text is shown to the user, for example
|
|
75759
|
-
* inside a branded error, where the stack of the wrapped error would only bury the actual cause.
|
|
75760
|
-
*/
|
|
75761
|
-
function formatUnknownErrorMessage(error) {
|
|
75762
|
-
if (error instanceof Error) {
|
|
75763
|
-
return error.message;
|
|
75764
|
-
}
|
|
75765
|
-
if (typeof error === 'string') {
|
|
75766
|
-
return error;
|
|
75767
|
-
}
|
|
75768
|
-
const serializedError = JSON.stringify(error, null, 2);
|
|
75769
|
-
return serializedError !== null && serializedError !== void 0 ? serializedError : String(error);
|
|
75770
|
-
}
|
|
75771
|
-
|
|
75772
76621
|
/**
|
|
75773
76622
|
* Git configuration key which lets Git read, write and delete files whose absolute path is longer than
|
|
75774
76623
|
* the Windows `MAX_PATH` limit of 260 characters.
|