@promptbook/cli 0.114.0-1 → 0.114.0-3
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/README.md +16 -15
- package/apps/agents-server/next.config.ts +11 -0
- package/apps/agents-server/package.json +6 -4
- package/apps/agents-server/playwright.config.ts +28 -38
- package/apps/agents-server/scripts/build-agents-server.js +62 -0
- package/apps/agents-server/scripts/build-e2e.js +38 -0
- package/apps/agents-server/scripts/ensure-root-dependencies.js +86 -0
- package/apps/agents-server/scripts/prerender-homepage.js +1 -1
- package/apps/agents-server/scripts/run-e2e-tests.js +34 -0
- package/apps/agents-server/scripts/run-npm.js +42 -0
- package/apps/agents-server/src/app/admin/email-server/page.tsx +14 -6
- package/apps/agents-server/src/app/api/elevenlabs/tts/route.ts +3 -3
- package/apps/agents-server/src/app/api/onboarding/book/route.ts +7 -6
- package/apps/agents-server/src/app/layout.tsx +6 -0
- package/apps/agents-server/src/app/superadmin/servers/ServersRegistryTable.tsx +105 -102
- package/apps/agents-server/src/app/superadmin/servers/useServersRegistryState.ts +15 -7
- package/apps/agents-server/src/components/AgentProjectDnsInstructions/AgentProjectDnsInstructions.tsx +11 -11
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ManGoBookEditor.tsx +82 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/WizardShell.tsx +2 -2
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/BookStep.tsx +13 -16
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/ZadaniStep.tsx +4 -4
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/config/bookSections.ts +23 -16
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/lib/bookSource.ts +54 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/bookService.ts +15 -8
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/createManGoAgentSource.ts +3 -37
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/createManGoOpenEditorRequest.ts +1 -1
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/state/OnboardingProvider.tsx +2 -2
- package/apps/agents-server/src/components/UsersList/CreateUserDialog.tsx +13 -22
- package/apps/agents-server/src/components/UsersList/PasswordGeneratorDialog.tsx +216 -0
- package/apps/agents-server/src/components/UsersList/UsersList.tsx +16 -11
- package/apps/agents-server/src/components/UsersList/generateSecurePassword.ts +112 -24
- package/apps/agents-server/src/components/UsersList/userDialogClassNames.ts +11 -0
- package/apps/agents-server/src/languages/ServerTranslationKeys.ts +11 -0
- package/apps/agents-server/src/languages/translations/czech.yaml +11 -0
- package/apps/agents-server/src/languages/translations/english.yaml +11 -0
- package/apps/agents-server/src/utils/agentProjects/agentProjectHrefs.ts +11 -0
- package/apps/agents-server/src/utils/agentProjects/createAgentProjectDnsRecords.ts +53 -7
- package/apps/agents-server/src/utils/agentProjects/createAgentProjectMarkdownReferences.ts +37 -27
- package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentBooks.ts +2 -13
- package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentRuntime.ts +21 -73
- package/apps/agents-server/src/utils/stalwart/createEmailDnsInstructions.ts +9 -5
- package/apps/agents-server/src/utils/stalwart/readStalwartEmailSnapshot.ts +23 -5
- package/apps/agents-server/src/utils/stalwart/stalwartBootstrap.ts +2 -1
- package/apps/agents-server/src/utils/stalwart/stalwartMailBridge.ts +7 -0
- package/apps/agents-server/tests/e2e/e2eEnvironment.cjs +49 -0
- package/esm/index.es.js +1105 -273
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +7 -0
- package/esm/scripts/run-codex-prompts/git/coderGitSync.d.ts +43 -0
- package/esm/scripts/run-codex-prompts/git/commitChanges.d.ts +3 -0
- package/esm/scripts/run-codex-prompts/main/resolvePromptRunner.d.ts +8 -1
- package/esm/scripts/run-codex-prompts/ping/buildCoderPingPrompt.d.ts +20 -0
- package/esm/scripts/run-codex-prompts/ping/extractCoderPingAnswer.d.ts +9 -0
- package/esm/scripts/run-codex-prompts/ping/pingCoderHarness.d.ts +23 -0
- package/esm/scripts/run-codex-prompts/ping/printCoderPingResult.d.ts +5 -0
- package/esm/scripts/run-codex-prompts/prompts/findNextTodoPrompt.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +27 -0
- package/esm/scripts/run-codex-prompts/prompts/listRunnablePrompts.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/prompts/replacePromptTodoStatusLine.d.ts +7 -0
- package/esm/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +16 -0
- package/esm/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +9 -0
- package/esm/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -2
- package/esm/scripts/run-codex-prompts/testing/runTestBefore.d.ts +24 -0
- package/esm/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +1 -0
- package/esm/scripts/verify-prompts/verify-prompts.d.ts +5 -0
- package/esm/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.d.ts +1 -15
- package/esm/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.d.ts +1 -1
- package/esm/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.d.ts +0 -4
- package/esm/src/book-components/Chat/utils/$provideServerDomWindow.d.ts +11 -0
- package/esm/src/book-components/Chat/utils/renderMarkdown.d.ts +7 -0
- package/esm/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +7 -0
- package/esm/src/cli/cli-commands/coder/agentCodingFile.d.ts +2 -3
- package/esm/src/cli/cli-commands/coder/ping.d.ts +10 -0
- package/esm/src/cli/cli-commands/coder/ping.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/coder.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/coderGitSyncCliOptions.d.ts +34 -0
- package/esm/src/cli/cli-commands/common/coderGitSyncCliOptions.test.d.ts +1 -0
- package/esm/src/cli/common/loadPromptsModule.d.ts +16 -0
- package/esm/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +1 -1
- package/esm/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +1 -1
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +1 -1
- package/esm/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.d.ts +1 -1
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsStreamRunner.d.ts +1 -1
- package/esm/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.d.ts +1 -1
- package/esm/src/llm-providers/openai/OpenAiCompatibleNonChatPromptCaller.d.ts +1 -1
- package/esm/src/llm-providers/openai/OpenAiCompatibleRequestManager.d.ts +1 -1
- package/esm/src/llm-providers/openai/utils/callOpenAiCompatibleChatModel.d.ts +1 -1
- package/esm/src/llm-providers/openai/utils/loadOpenAiAgentsModule.d.ts +203 -0
- package/esm/src/llm-providers/openai/utils/uploadFilesToOpenAi.d.ts +1 -1
- package/esm/src/utils/misc/createLazyModuleLoader.d.ts +14 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.ts +1 -15
- package/src/book-2.0/book-language-documentation/bookLanguageDocumentationExamples.ts +1 -2
- package/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.ts +92 -32
- package/src/book-2.0/book-language-documentation/czechBookLanguageManualDictionary.ts +16 -39
- package/src/book-2.0/book-language-documentation/englishBookLanguageManualDictionary.ts +16 -36
- package/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.ts +9 -1
- package/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.ts +4 -51
- package/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.ts +291 -4
- package/src/book-3.0/LiteAgent.ts +11 -9
- package/src/book-components/Chat/utils/$provideServerDomWindow.ts +77 -0
- package/src/book-components/Chat/utils/renderMarkdown.ts +135 -32
- package/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.ts +14 -0
- package/src/cli/cli-commands/agents-server/buildAgentsServer/ensureAgentsServerBuild.ts +1 -0
- package/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.ts +1 -0
- package/src/cli/cli-commands/coder/add.ts +40 -12
- package/src/cli/cli-commands/coder/agentCodingFile.ts +6 -129
- package/src/cli/cli-commands/coder/generate-boilerplates.ts +31 -5
- package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +1 -1
- package/src/cli/cli-commands/coder/init.ts +27 -1
- package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
- package/src/cli/cli-commands/coder/ping.ts +72 -0
- package/src/cli/cli-commands/coder/run.ts +25 -2
- package/src/cli/cli-commands/coder/verify.ts +27 -12
- package/src/cli/cli-commands/coder.ts +4 -0
- package/src/cli/cli-commands/common/coderGitSyncCliOptions.ts +78 -0
- package/src/cli/cli-commands/run/prepareRunCommandResources.ts +2 -1
- package/src/cli/cli-commands/run/resolveRunInputParameters.ts +2 -1
- package/src/cli/cli-commands/runInteractiveChatbot.ts +2 -1
- package/src/cli/common/$provideLlmToolsForCli.ts +2 -1
- package/src/cli/common/loadPromptsModule.ts +13 -0
- package/src/conversion/archive/loadArchive.ts +2 -1
- package/src/conversion/archive/loadJsZipModule.ts +10 -0
- package/src/conversion/archive/saveArchive.ts +2 -1
- package/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionTools.ts +13 -1
- package/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.ts +13 -1
- package/src/llm-providers/openai/OpenAiAgentKitExecutionTools.ts +6 -2
- package/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.ts +7 -5
- package/src/llm-providers/openai/OpenAiAssistantExecutionTools.ts +1 -1
- package/src/llm-providers/openai/OpenAiAssistantExecutionToolsStreamRunner.ts +1 -1
- package/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.ts +1 -1
- package/src/llm-providers/openai/OpenAiCompatibleNonChatPromptCaller.ts +1 -1
- package/src/llm-providers/openai/OpenAiCompatibleRequestManager.ts +12 -1
- package/src/llm-providers/openai/utils/callOpenAiCompatibleChatModel.ts +1 -1
- package/src/llm-providers/openai/utils/loadOpenAiAgentsModule.ts +11 -0
- package/src/llm-providers/openai/utils/uploadFilesToOpenAi.ts +1 -1
- package/src/other/templates/getTemplatesPipelineCollection.ts +731 -923
- package/src/remote-server/createRemoteClient.ts +12 -1
- package/src/scrapers/website/WebsiteScraper.ts +22 -2
- package/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.ts +101 -0
- package/src/utils/misc/createLazyModuleLoader.ts +27 -0
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -1
- package/umd/index.umd.js +1180 -342
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +7 -0
- package/umd/scripts/run-codex-prompts/git/coderGitSync.d.ts +43 -0
- package/umd/scripts/run-codex-prompts/git/commitChanges.d.ts +3 -0
- package/umd/scripts/run-codex-prompts/main/resolvePromptRunner.d.ts +8 -1
- package/umd/scripts/run-codex-prompts/ping/buildCoderPingPrompt.d.ts +20 -0
- package/umd/scripts/run-codex-prompts/ping/extractCoderPingAnswer.d.ts +9 -0
- package/umd/scripts/run-codex-prompts/ping/pingCoderHarness.d.ts +23 -0
- package/umd/scripts/run-codex-prompts/ping/printCoderPingResult.d.ts +5 -0
- package/umd/scripts/run-codex-prompts/prompts/findNextTodoPrompt.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +27 -0
- package/umd/scripts/run-codex-prompts/prompts/listRunnablePrompts.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/prompts/replacePromptTodoStatusLine.d.ts +7 -0
- package/umd/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +16 -0
- package/umd/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +9 -0
- package/umd/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -2
- package/umd/scripts/run-codex-prompts/testing/runTestBefore.d.ts +24 -0
- package/umd/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +1 -0
- package/umd/scripts/verify-prompts/verify-prompts.d.ts +5 -0
- package/umd/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.d.ts +1 -15
- package/umd/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.d.ts +1 -1
- package/umd/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.d.ts +0 -4
- package/umd/src/book-components/Chat/utils/$provideServerDomWindow.d.ts +11 -0
- package/umd/src/book-components/Chat/utils/renderMarkdown.d.ts +7 -0
- package/umd/src/cli/cli-commands/agents-server/buildAgentsServer/createAgentsServerRuntimeEnvironment.d.ts +7 -0
- package/umd/src/cli/cli-commands/coder/agentCodingFile.d.ts +2 -3
- package/umd/src/cli/cli-commands/coder/ping.d.ts +10 -0
- package/umd/src/cli/cli-commands/coder/ping.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/coder.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/coderGitSyncCliOptions.d.ts +34 -0
- package/umd/src/cli/cli-commands/common/coderGitSyncCliOptions.test.d.ts +1 -0
- package/umd/src/cli/common/loadPromptsModule.d.ts +16 -0
- package/umd/src/llm-providers/anthropic-claude/AnthropicClaudeExecutionTools.d.ts +1 -1
- package/umd/src/llm-providers/azure-openai/AzureOpenAiExecutionTools.d.ts +1 -1
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionTools.d.ts +1 -1
- package/umd/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.d.ts +1 -1
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsStreamRunner.d.ts +1 -1
- package/umd/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.d.ts +1 -1
- package/umd/src/llm-providers/openai/OpenAiCompatibleNonChatPromptCaller.d.ts +1 -1
- package/umd/src/llm-providers/openai/OpenAiCompatibleRequestManager.d.ts +1 -1
- package/umd/src/llm-providers/openai/utils/callOpenAiCompatibleChatModel.d.ts +1 -1
- package/umd/src/llm-providers/openai/utils/loadOpenAiAgentsModule.d.ts +203 -0
- package/umd/src/llm-providers/openai/utils/uploadFilesToOpenAi.d.ts +1 -1
- package/umd/src/utils/misc/createLazyModuleLoader.d.ts +14 -0
- package/umd/src/version.d.ts +1 -1
- package/apps/agents-server/src/app/api/onboarding/draft/route.ts +0 -23
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/BookLanguagePanel.tsx +0 -125
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/MarkdownBookEditor.tsx +0 -154
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/MarkdownPreview.tsx +0 -188
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/draftService.ts +0 -32
package/esm/index.es.js
CHANGED
|
@@ -9,16 +9,11 @@ import moment from 'moment';
|
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import { createWriteStream, mkdirSync, writeFileSync, statSync, readFileSync, existsSync, promises } from 'fs';
|
|
11
11
|
import * as dotenv from 'dotenv';
|
|
12
|
-
import prompts from 'prompts';
|
|
13
12
|
import * as readline from 'readline';
|
|
14
13
|
import { emitKeypressEvents, clearLine, cursorTo, createInterface } from 'readline';
|
|
15
14
|
import { forTime, forEver } from 'waitasecond';
|
|
16
15
|
import hexEncoder from 'crypto-js/enc-hex';
|
|
17
16
|
import sha256 from 'crypto-js/sha256';
|
|
18
|
-
import { io } from 'socket.io-client';
|
|
19
|
-
import JSZip from 'jszip';
|
|
20
|
-
import { Readability } from '@mozilla/readability';
|
|
21
|
-
import { JSDOM } from 'jsdom';
|
|
22
17
|
import CryptoJS from 'crypto-js';
|
|
23
18
|
import showdown from 'showdown';
|
|
24
19
|
import glob from 'glob-promise';
|
|
@@ -29,19 +24,13 @@ import * as OpenApiValidator from 'express-openapi-validator';
|
|
|
29
24
|
import swaggerUi from 'swagger-ui-express';
|
|
30
25
|
import { createElement } from 'react';
|
|
31
26
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
32
|
-
import Anthropic from '@anthropic-ai/sdk';
|
|
33
27
|
import Bottleneck from 'bottleneck';
|
|
34
|
-
import { OpenAIClient, AzureKeyCredential } from '@azure/openai';
|
|
35
28
|
import { Subject, BehaviorSubject } from 'rxjs';
|
|
36
|
-
import { fileSearchTool, tool, Agent as Agent$1, webSearchTool, run, setDefaultOpenAIClient, setDefaultOpenAIKey } from '@openai/agents';
|
|
37
|
-
import OpenAI from 'openai';
|
|
38
|
-
import * as ts from 'typescript';
|
|
39
29
|
import ignore from 'ignore';
|
|
40
30
|
import { EventEmitter } from 'events';
|
|
41
31
|
import { tmpdir } from 'os';
|
|
42
32
|
import { lookup, extension } from 'mime-types';
|
|
43
33
|
import papaparse from 'papaparse';
|
|
44
|
-
import { Client } from 'pg';
|
|
45
34
|
import '@supabase/supabase-js';
|
|
46
35
|
import { pathToFileURL } from 'url';
|
|
47
36
|
|
|
@@ -59,7 +48,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
59
48
|
* @generated
|
|
60
49
|
* @see https://github.com/webgptorg/promptbook
|
|
61
50
|
*/
|
|
62
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-
|
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-3';
|
|
63
52
|
/**
|
|
64
53
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
65
54
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -3293,6 +3282,12 @@ const PTBK_AGENTS_SERVER_BUILD_WORKER_COUNT_ENV = 'PTBK_AGENTS_SERVER_BUILD_WORK
|
|
|
3293
3282
|
* @private internal constant of `buildAgentsServer`
|
|
3294
3283
|
*/
|
|
3295
3284
|
const PTBK_AGENTS_SERVER_IGNORE_NEXT_VALIDATION_ENV = 'PTBK_AGENTS_SERVER_IGNORE_NEXT_VALIDATION';
|
|
3285
|
+
/**
|
|
3286
|
+
* Environment variable that disables throwaway webpack filesystem caches for CLI-owned production builds.
|
|
3287
|
+
*
|
|
3288
|
+
* @private internal constant of `buildAgentsServer`
|
|
3289
|
+
*/
|
|
3290
|
+
const PTBK_AGENTS_SERVER_DISABLE_WEBPACK_FILESYSTEM_CACHE_ENV = 'PTBK_AGENTS_SERVER_DISABLE_WEBPACK_FILESYSTEM_CACHE';
|
|
3296
3291
|
/**
|
|
3297
3292
|
* Conservative Next.js build worker count used by CLI-owned Agents Server production builds.
|
|
3298
3293
|
*
|
|
@@ -3317,6 +3312,11 @@ function createAgentsServerRuntimeEnvironment(environment, nodeModulesPath, opti
|
|
|
3317
3312
|
[PTBK_AGENTS_SERVER_IGNORE_NEXT_VALIDATION_ENV]: 'true',
|
|
3318
3313
|
}
|
|
3319
3314
|
: {}),
|
|
3315
|
+
...(options.isWebpackFilesystemCacheDisabled
|
|
3316
|
+
? {
|
|
3317
|
+
[PTBK_AGENTS_SERVER_DISABLE_WEBPACK_FILESYSTEM_CACHE_ENV]: 'true',
|
|
3318
|
+
}
|
|
3319
|
+
: {}),
|
|
3320
3320
|
};
|
|
3321
3321
|
}
|
|
3322
3322
|
/**
|
|
@@ -4050,6 +4050,7 @@ async function ensureAgentsServerBuild(options = {}) {
|
|
|
4050
4050
|
});
|
|
4051
4051
|
const buildEnvironment = createAgentsServerRuntimeEnvironment(environment, preparedRuntime.nodeModulesPath, {
|
|
4052
4052
|
isNextValidationIgnored: preparedRuntime.isAppPathMaterialized,
|
|
4053
|
+
isWebpackFilesystemCacheDisabled: true,
|
|
4053
4054
|
});
|
|
4054
4055
|
if (!options.isBuildForced &&
|
|
4055
4056
|
(await isAgentsServerBuildCacheCurrent({
|
|
@@ -26966,12 +26967,12 @@ function buildControlPills(options) {
|
|
|
26966
26967
|
* Builds the coder-run control pills shown in the footer box.
|
|
26967
26968
|
*/
|
|
26968
26969
|
function buildCoderRunControlPills(options) {
|
|
26969
|
-
const { pauseControl, pendingEnterLabel, isEndAfterCurrentPromptRequested, sessionTotal } = options;
|
|
26970
|
+
const { phase, pauseControl, pendingEnterLabel, isEndAfterCurrentPromptRequested, sessionTotal } = options;
|
|
26970
26971
|
return buildControlPills({
|
|
26971
26972
|
pauseControl,
|
|
26972
26973
|
pendingEnterLabel,
|
|
26973
26974
|
additionalControls: [
|
|
26974
|
-
buildSkipCurrentWaitControl(),
|
|
26975
|
+
...(phase === 'waiting' ? [buildSkipCurrentWaitControl()] : []),
|
|
26975
26976
|
buildEndAfterCurrentPromptControl(isEndAfterCurrentPromptRequested, sessionTotal),
|
|
26976
26977
|
],
|
|
26977
26978
|
});
|
|
@@ -28226,6 +28227,13 @@ function toPosixPath(filePath) {
|
|
|
28226
28227
|
* Environment variable read by the shell wrapper to tee live output into the temporary runtime log file.
|
|
28227
28228
|
*/
|
|
28228
28229
|
const PTBK_CODER_LOG_FILE_ENV_NAME = 'PTBK_CODER_LOG_FILE';
|
|
28230
|
+
/**
|
|
28231
|
+
* Log line which separates the raw script input from the raw script output of one execution section.
|
|
28232
|
+
*
|
|
28233
|
+
* Readers of a runtime log split on this marker to look only at what the harness really produced,
|
|
28234
|
+
* without the generated script and the prompt it embeds.
|
|
28235
|
+
*/
|
|
28236
|
+
const SCRIPT_EXECUTION_LOG_RAW_OUTPUT_MARKER = '--- raw output ---';
|
|
28229
28237
|
/**
|
|
28230
28238
|
* Small bash wrapper that preserves stdout/stderr streams while teeing both into the runtime log file.
|
|
28231
28239
|
*/
|
|
@@ -28261,7 +28269,7 @@ async function appendScriptExecutionLogStart({ scriptPath, scriptContent, logPat
|
|
|
28261
28269
|
--- raw input ---
|
|
28262
28270
|
${block(normalizedInput)}
|
|
28263
28271
|
|
|
28264
|
-
|
|
28272
|
+
${SCRIPT_EXECUTION_LOG_RAW_OUTPUT_MARKER}
|
|
28265
28273
|
`);
|
|
28266
28274
|
await appendFile(logPath, `${logSection}\n`, 'utf-8');
|
|
28267
28275
|
}
|
|
@@ -29552,6 +29560,7 @@ function buildCodexScript(options) {
|
|
|
29552
29560
|
` -c model_reasoning_effort="${thinkingLevel}" \\`,
|
|
29553
29561
|
` --ask-for-approval ${options.askForApproval} \\`,
|
|
29554
29562
|
` exec --model ${options.model} \\`,
|
|
29563
|
+
...(options.isMachineReadableProgressEnabled ? [' --json \\'] : []),
|
|
29555
29564
|
' --local-provider none \\',
|
|
29556
29565
|
` --sandbox ${options.sandbox} \\`,
|
|
29557
29566
|
` -C ${projectPath} \\`,
|
|
@@ -29868,6 +29877,10 @@ function matchesAnyPattern(text, patterns) {
|
|
|
29868
29877
|
* Output line that marks finished Codex usage summary.
|
|
29869
29878
|
*/
|
|
29870
29879
|
const CODEX_COMPLETION_LINE = /^\s*tokens used\b/i;
|
|
29880
|
+
/**
|
|
29881
|
+
* Output line that marks the completed Codex turn in JSONL output mode.
|
|
29882
|
+
*/
|
|
29883
|
+
const CODEX_JSON_COMPLETION_LINE = /^\s*\{"type":"turn\.(?:completed|failed)"/u;
|
|
29871
29884
|
/**
|
|
29872
29885
|
* Idle timeout after completion marker to capture trailing output.
|
|
29873
29886
|
*/
|
|
@@ -29944,6 +29957,7 @@ class OpenAiCodexRunner {
|
|
|
29944
29957
|
sandbox: this.options.sandbox,
|
|
29945
29958
|
askForApproval: this.options.askForApproval,
|
|
29946
29959
|
allowCredits: this.options.allowCredits,
|
|
29960
|
+
isMachineReadableProgressEnabled: this.options.isMachineReadableProgressEnabled,
|
|
29947
29961
|
codexCommand: this.options.codexCommand,
|
|
29948
29962
|
});
|
|
29949
29963
|
for (let retryIndex = 0;; retryIndex++) {
|
|
@@ -29958,7 +29972,9 @@ class OpenAiCodexRunner {
|
|
|
29958
29972
|
const output = await $runGoScriptUntilMarkerIdle({
|
|
29959
29973
|
scriptPath: options.scriptPath,
|
|
29960
29974
|
scriptContent,
|
|
29961
|
-
completionLineMatcher:
|
|
29975
|
+
completionLineMatcher: this.options.isMachineReadableProgressEnabled
|
|
29976
|
+
? CODEX_JSON_COMPLETION_LINE
|
|
29977
|
+
: CODEX_COMPLETION_LINE,
|
|
29962
29978
|
idleTimeoutMs: CODEX_COMPLETION_IDLE_MS,
|
|
29963
29979
|
logPath: options.logPath,
|
|
29964
29980
|
shouldPrintLiveOutput: options.shouldPrintLiveOutput,
|
|
@@ -30208,6 +30224,7 @@ function createOpenAiCodexRunnerResolution(options) {
|
|
|
30208
30224
|
sandbox: 'danger-full-access',
|
|
30209
30225
|
askForApproval: 'never',
|
|
30210
30226
|
allowCredits: options.allowCredits,
|
|
30227
|
+
isMachineReadableProgressEnabled: options.isMachineReadableProgressEnabled,
|
|
30211
30228
|
});
|
|
30212
30229
|
if (!options.allowCredits && options.isVerbose === true) {
|
|
30213
30230
|
console.info(colors.gray('OpenAI Codex credit spending is disabled. Use `--allow-credits` to explicitly opt in.'));
|
|
@@ -31443,6 +31460,7 @@ function buildCoderRunUiFrame(options) {
|
|
|
31443
31460
|
: [options.statusMessage, ...options.detailLines.map((detailLine) => `• ${detailLine}`)];
|
|
31444
31461
|
const visibleOutputLines = buildVisibleOutputLines(options.agentOutputLines);
|
|
31445
31462
|
const controls = buildCoderRunControlPills({
|
|
31463
|
+
phase: options.phase,
|
|
31446
31464
|
pauseControl: pausePresentation.pauseControl,
|
|
31447
31465
|
pendingEnterLabel: options.pendingEnterLabel,
|
|
31448
31466
|
isEndAfterCurrentPromptRequested: options.isEndAfterCurrentPromptRequested,
|
|
@@ -32306,6 +32324,7 @@ function createCoderRunOptionsForAgent(options) {
|
|
|
32306
32324
|
autoPull: options.autoPull,
|
|
32307
32325
|
agentName: options.agentName,
|
|
32308
32326
|
model: options.model,
|
|
32327
|
+
isMachineReadableProgressEnabled: options.isMachineReadableProgressEnabled,
|
|
32309
32328
|
priority: 0,
|
|
32310
32329
|
};
|
|
32311
32330
|
}
|
|
@@ -32927,8 +32946,12 @@ function readOptionalSigningKeyValue() {
|
|
|
32927
32946
|
* `options.includePaths` can restrict staging, `options.onlyPaths` can restrict the commit pathspec,
|
|
32928
32947
|
* `options.excludePaths` can keep temporary artifacts out of the created commit and
|
|
32929
32948
|
* `options.isEmptyCommitAllowed` keeps a round without any file change from failing.
|
|
32949
|
+
*
|
|
32950
|
+
* Note: The temporary commit message file is written inside the project, so it is always excluded from the commit
|
|
32951
|
+
* itself for projects which do not keep the Promptbook temporary directory out of version control.
|
|
32930
32952
|
*/
|
|
32931
32953
|
async function commitChanges(message, options) {
|
|
32954
|
+
var _a;
|
|
32932
32955
|
const projectPath = (options === null || options === void 0 ? void 0 : options.projectPath) || process.cwd();
|
|
32933
32956
|
const commitMessagePath = resolvePromptbookTemporaryPath(projectPath, 'ptbk-coder', 'commit-messages', `COMMIT_MESSAGE_${Date.now()}.txt`);
|
|
32934
32957
|
await mkdir(dirname(commitMessagePath), { recursive: true });
|
|
@@ -32936,7 +32959,10 @@ async function commitChanges(message, options) {
|
|
|
32936
32959
|
try {
|
|
32937
32960
|
const agentEnv = buildAgentGitEnv();
|
|
32938
32961
|
const signingFlag = buildAgentGitSigningFlag();
|
|
32939
|
-
await stageCommitChanges(projectPath, agentEnv, options === null || options === void 0 ? void 0 : options.includePaths,
|
|
32962
|
+
await stageCommitChanges(projectPath, agentEnv, options === null || options === void 0 ? void 0 : options.includePaths, [
|
|
32963
|
+
commitMessagePath,
|
|
32964
|
+
...((_a = options === null || options === void 0 ? void 0 : options.excludePaths) !== null && _a !== void 0 ? _a : []),
|
|
32965
|
+
]);
|
|
32940
32966
|
await runGitCommand({
|
|
32941
32967
|
command: buildGitCommitCommand({
|
|
32942
32968
|
commitMessagePath,
|
|
@@ -33295,6 +33321,21 @@ function appendCoderContext(prompt, context) {
|
|
|
33295
33321
|
`);
|
|
33296
33322
|
}
|
|
33297
33323
|
|
|
33324
|
+
/**
|
|
33325
|
+
* Maximum amount of test output embedded into an agent prompt.
|
|
33326
|
+
*/
|
|
33327
|
+
const MAX_TEST_OUTPUT_CHARS = 12000;
|
|
33328
|
+
/**
|
|
33329
|
+
* Limits test output while keeping the end of the output, where test runners usually print the failure summary.
|
|
33330
|
+
*/
|
|
33331
|
+
function limitTestOutput(testOutput) {
|
|
33332
|
+
const normalizedTestOutput = testOutput.trim();
|
|
33333
|
+
if (normalizedTestOutput.length <= MAX_TEST_OUTPUT_CHARS) {
|
|
33334
|
+
return normalizedTestOutput;
|
|
33335
|
+
}
|
|
33336
|
+
return `[..., test output truncated to the last ${MAX_TEST_OUTPUT_CHARS} characters...]\n${normalizedTestOutput.slice(-MAX_TEST_OUTPUT_CHARS)}`;
|
|
33337
|
+
}
|
|
33338
|
+
|
|
33298
33339
|
/**
|
|
33299
33340
|
* Runs the configured verification command inside the project root and returns its output.
|
|
33300
33341
|
*/
|
|
@@ -33315,10 +33356,6 @@ async function runPromptTestCommand(options) {
|
|
|
33315
33356
|
* Maximum number of coding attempts allowed for the same prompt when verification keeps failing.
|
|
33316
33357
|
*/
|
|
33317
33358
|
const MAX_PROMPT_TEST_ATTEMPTS = 3;
|
|
33318
|
-
/**
|
|
33319
|
-
* Maximum amount of verification output sent back to the coding agent as retry feedback.
|
|
33320
|
-
*/
|
|
33321
|
-
const MAX_TEST_FEEDBACK_OUTPUT_CHARS = 12000;
|
|
33322
33359
|
/**
|
|
33323
33360
|
* File extension used by generated shell scripts.
|
|
33324
33361
|
*/
|
|
@@ -33364,7 +33401,7 @@ async function runPromptWithTestFeedback(options) {
|
|
|
33364
33401
|
return { ...result, attemptCount, steps };
|
|
33365
33402
|
}
|
|
33366
33403
|
const fullVerificationOutput = formatUnknownErrorDetails(failedVerification.error);
|
|
33367
|
-
const feedbackVerificationOutput =
|
|
33404
|
+
const feedbackVerificationOutput = limitTestOutput(fullVerificationOutput);
|
|
33368
33405
|
if (attemptCount >= MAX_PROMPT_TEST_ATTEMPTS) {
|
|
33369
33406
|
console.error(colors.red(`Verification failed for ${options.promptLabel} after ${attemptCount} attempts.`));
|
|
33370
33407
|
throw new Error(buildFinalVerificationFailureMessage({
|
|
@@ -33494,19 +33531,6 @@ function buildFinalVerificationFailureMessage({ promptLabel, testCommand, attemp
|
|
|
33494
33531
|
\`\`\`
|
|
33495
33532
|
`);
|
|
33496
33533
|
}
|
|
33497
|
-
/**
|
|
33498
|
-
* Limits verification output before it is embedded back into the next coding prompt.
|
|
33499
|
-
*/
|
|
33500
|
-
function limitVerificationOutputForFeedback(verificationOutput) {
|
|
33501
|
-
const normalizedVerificationOutput = verificationOutput.trim();
|
|
33502
|
-
if (normalizedVerificationOutput.length <= MAX_TEST_FEEDBACK_OUTPUT_CHARS) {
|
|
33503
|
-
return normalizedVerificationOutput;
|
|
33504
|
-
}
|
|
33505
|
-
return spaceTrim(`
|
|
33506
|
-
[...verification output truncated to the last ${MAX_TEST_FEEDBACK_OUTPUT_CHARS} characters...]
|
|
33507
|
-
${normalizedVerificationOutput.slice(-MAX_TEST_FEEDBACK_OUTPUT_CHARS)}
|
|
33508
|
-
`);
|
|
33509
|
-
}
|
|
33510
33534
|
/**
|
|
33511
33535
|
* Derives a dedicated temp-script path for verification commands.
|
|
33512
33536
|
*/
|
|
@@ -41367,6 +41391,7 @@ function createLocalAgentRunOptions(options, localAgentRunnerLimits) {
|
|
|
41367
41391
|
autoClone: false,
|
|
41368
41392
|
maxMessageProcessingFailures: localAgentRunnerLimits.maxFailedAttempts,
|
|
41369
41393
|
maxParallelMessages: localAgentRunnerLimits.maxParallelMessages,
|
|
41394
|
+
isMachineReadableProgressEnabled: true,
|
|
41370
41395
|
};
|
|
41371
41396
|
}
|
|
41372
41397
|
|
|
@@ -42277,6 +42302,91 @@ function $initializeAgentsServerCommand(program) {
|
|
|
42277
42302
|
// Note: [🟡] Code for CLI command [agents-server](src/cli/cli-commands/agents-server.ts) should never be published outside of `@promptbook/cli`
|
|
42278
42303
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
42279
42304
|
|
|
42305
|
+
/**
|
|
42306
|
+
* Creates a loader which imports one module on the first call and reuses the very same module afterwards
|
|
42307
|
+
*
|
|
42308
|
+
* Note: [🐌] Heavy third-party dependencies are imported lazily to keep the startup of the Promptbook CLI fast.
|
|
42309
|
+
* A statically imported dependency is loaded every single time the bundle is loaded, even when the running
|
|
42310
|
+
* command never touches it. A lazily imported dependency is loaded only when the feature is really used.
|
|
42311
|
+
*
|
|
42312
|
+
* @example
|
|
42313
|
+
* const loadJsdomModule = createLazyModuleLoader(() => import('jsdom'));
|
|
42314
|
+
* const { JSDOM } = await loadJsdomModule();
|
|
42315
|
+
*
|
|
42316
|
+
* @private internal utility of Promptbook
|
|
42317
|
+
*/
|
|
42318
|
+
function createLazyModuleLoader(importModule) {
|
|
42319
|
+
let importedModulePromise = null;
|
|
42320
|
+
return function loadModule() {
|
|
42321
|
+
if (importedModulePromise === null) {
|
|
42322
|
+
importedModulePromise = importModule();
|
|
42323
|
+
}
|
|
42324
|
+
return importedModulePromise;
|
|
42325
|
+
};
|
|
42326
|
+
}
|
|
42327
|
+
// Note: [🐌] Do not convert the lazy `import(...)` calls back to static `import` statements, it would bring back the
|
|
42328
|
+
// slow startup of the `ptbk` CLI utility
|
|
42329
|
+
|
|
42330
|
+
/**
|
|
42331
|
+
* Loads the interactive terminal prompt library (`prompts`) on demand
|
|
42332
|
+
*
|
|
42333
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast - most commands never ask the user
|
|
42334
|
+
* anything interactively
|
|
42335
|
+
*
|
|
42336
|
+
* @private internal utility of Promptbook CLI
|
|
42337
|
+
*/
|
|
42338
|
+
const loadPromptsModule = createLazyModuleLoader(() => import('prompts'));
|
|
42339
|
+
// Note: [🟡] Code for CLI prompt loading [loadPromptsModule](src/cli/common/loadPromptsModule.ts) should never be published outside of `@promptbook/cli`
|
|
42340
|
+
|
|
42341
|
+
/**
|
|
42342
|
+
* Description block shared by the `ptbk coder` commands which can synchronize their changes with git.
|
|
42343
|
+
*
|
|
42344
|
+
* @private internal utility of `promptbookCli`
|
|
42345
|
+
*/
|
|
42346
|
+
const CODER_GIT_SYNC_DESCRIPTION = spaceTrim$1(`
|
|
42347
|
+
Git synchronization:
|
|
42348
|
+
- --auto-pull pulls the latest changes before this command changes anything
|
|
42349
|
+
- --commit commits the changes made by this command
|
|
42350
|
+
- --auto-push pushes the created commit to the remote repository
|
|
42351
|
+
`);
|
|
42352
|
+
/**
|
|
42353
|
+
* Registers the shared `--commit`, `--auto-push` and `--auto-pull` flags on a `ptbk coder` command.
|
|
42354
|
+
*
|
|
42355
|
+
* Note: Unlike `ptbk coder run`, which commits by default and opts out through `--no-commit`,
|
|
42356
|
+
* these commands never touch git unless the flags are used explicitly.
|
|
42357
|
+
*
|
|
42358
|
+
* @private internal utility of `promptbookCli`
|
|
42359
|
+
*/
|
|
42360
|
+
function addCoderGitSyncOptions(command) {
|
|
42361
|
+
command.option('--commit', 'Commit the changes made by this command with the coding-agent git identity', false);
|
|
42362
|
+
command.option('--auto-push', 'Automatically git push the created commit, requires --commit', false);
|
|
42363
|
+
command.option('--auto-pull', 'Automatically git pull the latest changes before this command changes anything', false);
|
|
42364
|
+
}
|
|
42365
|
+
/**
|
|
42366
|
+
* Converts the Commander git synchronization flags into normalized git synchronization options.
|
|
42367
|
+
*
|
|
42368
|
+
* @private internal utility of `promptbookCli`
|
|
42369
|
+
*/
|
|
42370
|
+
function normalizeCoderGitSyncCliOptions(cliOptions) {
|
|
42371
|
+
if (cliOptions.autoPush && !cliOptions.commit) {
|
|
42372
|
+
throw new NotAllowed(spaceTrim$1(`
|
|
42373
|
+
Flag \`--auto-push\` can be used only together with \`--commit\`.
|
|
42374
|
+
|
|
42375
|
+
**There is nothing to push when the changes are not committed.**
|
|
42376
|
+
|
|
42377
|
+
Actionable hint:
|
|
42378
|
+
- Add \`--commit\`, for example \`ptbk coder init --commit --auto-push\`.
|
|
42379
|
+
`));
|
|
42380
|
+
}
|
|
42381
|
+
return {
|
|
42382
|
+
isCommitEnabled: cliOptions.commit,
|
|
42383
|
+
isAutoPushEnabled: cliOptions.autoPush,
|
|
42384
|
+
isAutoPullEnabled: cliOptions.autoPull,
|
|
42385
|
+
};
|
|
42386
|
+
}
|
|
42387
|
+
// Note: [🟡] Code for CLI git synchronization options [coderGitSyncCliOptions](src/cli/cli-commands/common/coderGitSyncCliOptions.ts) should never be published outside of `@promptbook/cli`
|
|
42388
|
+
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
42389
|
+
|
|
42280
42390
|
/**
|
|
42281
42391
|
* Relative path to the root prompts directory used by Promptbook coder utilities.
|
|
42282
42392
|
*
|
|
@@ -42530,15 +42640,17 @@ const FALLBACK_PROMPT_SLUG = 'prompt';
|
|
|
42530
42640
|
*/
|
|
42531
42641
|
function $initializeCoderAddCommand(program) {
|
|
42532
42642
|
const command = program.command('add');
|
|
42533
|
-
command.description(spaceTrim$1(`
|
|
42534
|
-
|
|
42643
|
+
command.description(spaceTrim$1((block) => `
|
|
42644
|
+
Add one ready-to-run prompt file to the queue
|
|
42535
42645
|
|
|
42536
|
-
|
|
42537
|
-
|
|
42538
|
-
|
|
42539
|
-
|
|
42540
|
-
|
|
42541
|
-
|
|
42646
|
+
Provide the description as an argument, pipe it through stdin, or run without arguments to type it interactively:
|
|
42647
|
+
- \`ptbk coder add "some new feature"\`
|
|
42648
|
+
- \`ptbk coder add --priority 1 "some new feature"\`
|
|
42649
|
+
- \`ptbk coder add <<EOF ... EOF\`
|
|
42650
|
+
- \`ptbk coder add\`
|
|
42651
|
+
|
|
42652
|
+
${block(CODER_GIT_SYNC_DESCRIPTION)}
|
|
42653
|
+
`));
|
|
42542
42654
|
command.argument('[description]', 'Plain-language description of the feature or task to implement');
|
|
42543
42655
|
command.option('--priority <priority>', 'Priority of the new prompt — higher priorities run first (rendered as trailing `!` markers)', parsePriorityOption, 0);
|
|
42544
42656
|
command.option('--template <template>', spaceTrim$1(`
|
|
@@ -42548,15 +42660,26 @@ function $initializeCoderAddCommand(program) {
|
|
|
42548
42660
|
.map(({ id }) => id)
|
|
42549
42661
|
.join(', ')}) or a markdown file path relative to the current project root.
|
|
42550
42662
|
`));
|
|
42663
|
+
addCoderGitSyncOptions(command);
|
|
42551
42664
|
command.action(handleActionErrors(async (descriptionArgument, cliOptions) => {
|
|
42552
42665
|
const { priority, template: templateOption } = cliOptions;
|
|
42666
|
+
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
42667
|
+
const projectPath = process.cwd();
|
|
42553
42668
|
const description = await resolveCoderPromptDescription(descriptionArgument);
|
|
42554
|
-
|
|
42555
|
-
|
|
42669
|
+
// Note: Import the git synchronization dynamically to keep the CLI fast for runs without `--commit`
|
|
42670
|
+
const { $commitCoderChanges, $pullCoderChanges } = await Promise.resolve().then(function () { return coderGitSync; });
|
|
42671
|
+
await $pullCoderChanges({ gitSync, projectPath });
|
|
42672
|
+
const { /* filePath,*/ emojiTag } = await addCoderPrompt({
|
|
42673
|
+
projectPath,
|
|
42556
42674
|
description,
|
|
42557
42675
|
priority,
|
|
42558
42676
|
templateOption,
|
|
42559
42677
|
});
|
|
42678
|
+
await $commitCoderChanges({
|
|
42679
|
+
gitSync,
|
|
42680
|
+
projectPath,
|
|
42681
|
+
commitMessage: `${emojiTag} Add prompt`,
|
|
42682
|
+
});
|
|
42560
42683
|
}));
|
|
42561
42684
|
}
|
|
42562
42685
|
/**
|
|
@@ -42630,6 +42753,7 @@ async function resolveCoderPromptDescription(descriptionArgument) {
|
|
|
42630
42753
|
}
|
|
42631
42754
|
return standardInputDescription;
|
|
42632
42755
|
}
|
|
42756
|
+
const { default: prompts } = await loadPromptsModule();
|
|
42633
42757
|
const response = await prompts({
|
|
42634
42758
|
type: 'text',
|
|
42635
42759
|
name: 'description',
|
|
@@ -43050,9 +43174,11 @@ function parseIntOption(value) {
|
|
|
43050
43174
|
*/
|
|
43051
43175
|
function $initializeCoderGenerateBoilerplatesCommand(program) {
|
|
43052
43176
|
const command = program.command('generate-boilerplates');
|
|
43053
|
-
command.description(spaceTrim$1(`
|
|
43054
|
-
|
|
43055
|
-
|
|
43177
|
+
command.description(spaceTrim$1((block) => `
|
|
43178
|
+
Generate prompt boilerplate files with unique emoji tags
|
|
43179
|
+
|
|
43180
|
+
${block(CODER_GIT_SYNC_DESCRIPTION)}
|
|
43181
|
+
`));
|
|
43056
43182
|
command.option('--count <count>', `Number of prompt boilerplate files to generate`, '5');
|
|
43057
43183
|
command.option('--template <template>', spaceTrim$1(`
|
|
43058
43184
|
Prompt template to use.
|
|
@@ -43061,14 +43187,25 @@ function $initializeCoderGenerateBoilerplatesCommand(program) {
|
|
|
43061
43187
|
.map(({ id }) => id)
|
|
43062
43188
|
.join(', ')}) or a markdown file path relative to the current project root.
|
|
43063
43189
|
`));
|
|
43190
|
+
addCoderGitSyncOptions(command);
|
|
43064
43191
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
43065
43192
|
const { count: countOption, template: templateOption } = cliOptions;
|
|
43066
43193
|
const filesCount = parseFilesCount(countOption);
|
|
43194
|
+
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
43195
|
+
const projectPath = process.cwd();
|
|
43196
|
+
// Note: Import the git synchronization dynamically to keep the CLI fast for runs without `--commit`
|
|
43197
|
+
const { $commitCoderChanges, $pullCoderChanges } = await Promise.resolve().then(function () { return coderGitSync; });
|
|
43198
|
+
await $pullCoderChanges({ gitSync, projectPath });
|
|
43067
43199
|
await generatePromptBoilerplate({
|
|
43068
|
-
projectPath
|
|
43200
|
+
projectPath,
|
|
43069
43201
|
filesCount,
|
|
43070
43202
|
templateOption,
|
|
43071
43203
|
});
|
|
43204
|
+
await $commitCoderChanges({
|
|
43205
|
+
gitSync,
|
|
43206
|
+
projectPath,
|
|
43207
|
+
commitMessage: `Prompts ${filesCount}x`,
|
|
43208
|
+
});
|
|
43072
43209
|
return process.exit(0);
|
|
43073
43210
|
}));
|
|
43074
43211
|
}
|
|
@@ -43481,6 +43618,27 @@ function resolveCheckedHarnessDefinitions(harnessNames) {
|
|
|
43481
43618
|
}
|
|
43482
43619
|
// Note: [🟡] Code for CLI harness installation orchestration [$ensureHarnessInstallations](src/cli/cli-commands/common/harness/$ensureHarnessInstallations.ts) should never be published outside of `@promptbook/cli`
|
|
43483
43620
|
|
|
43621
|
+
/**
|
|
43622
|
+
* Relative path to the Promptbook Coder quick-reference file initialized in project roots.
|
|
43623
|
+
*
|
|
43624
|
+
* @private internal utility of `ptbk coder`
|
|
43625
|
+
*/
|
|
43626
|
+
const AGENT_CODING_FILE_PATH = 'AGENT_CODING.md';
|
|
43627
|
+
/**
|
|
43628
|
+
* Returns the default coder `AGENT_CODING.md` quick-reference content.
|
|
43629
|
+
*
|
|
43630
|
+
* @private internal utility of `ptbk coder`
|
|
43631
|
+
*/
|
|
43632
|
+
function getDefaultCoderAgentCodingFileContent() {
|
|
43633
|
+
return spaceTrim$1(`
|
|
43634
|
+
# ✨ Promptbook Coder agent coding
|
|
43635
|
+
|
|
43636
|
+
This project is using [Promptbook Coder](https://coder.ptbk.io) or run \`ptbk coder\`!
|
|
43637
|
+
`);
|
|
43638
|
+
}
|
|
43639
|
+
// Note: [🟡] Code for coder AGENT_CODING file boilerplate [agentCodingFile](src/cli/cli-commands/coder/agentCodingFile.ts) should never be published outside of `@promptbook/cli`
|
|
43640
|
+
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
43641
|
+
|
|
43484
43642
|
/**
|
|
43485
43643
|
* Relative path to the shared coder context file initialized in project roots.
|
|
43486
43644
|
*
|
|
@@ -43508,106 +43666,6 @@ function getDefaultCoderAgentsFileContent() {
|
|
|
43508
43666
|
// Note: [🟡] Code for coder AGENTS file boilerplate [agentsFile](src/cli/cli-commands/coder/agentsFile.ts) should never be published outside of `@promptbook/cli`
|
|
43509
43667
|
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
43510
43668
|
|
|
43511
|
-
/**
|
|
43512
|
-
* Normalizes one project-relative path for human-readable CLI output and markdown.
|
|
43513
|
-
*
|
|
43514
|
-
* @private internal utility of `ptbk coder`
|
|
43515
|
-
*/
|
|
43516
|
-
function formatDisplayPath(relativePath) {
|
|
43517
|
-
return relativePath.replace(/\\/gu, '/');
|
|
43518
|
-
}
|
|
43519
|
-
// Note: [🟡] Code for coder path formatting [formatDisplayPath](src/cli/cli-commands/coder/formatDisplayPath.ts) should never be published outside of `@promptbook/cli`
|
|
43520
|
-
|
|
43521
|
-
/**
|
|
43522
|
-
* Relative path to the Promptbook Coder quick-reference file initialized in project roots.
|
|
43523
|
-
*
|
|
43524
|
-
* @private internal utility of `ptbk coder`
|
|
43525
|
-
*/
|
|
43526
|
-
const AGENT_CODING_FILE_PATH = 'AGENT_CODING.md';
|
|
43527
|
-
/**
|
|
43528
|
-
* Returns the default coder `AGENT_CODING.md` quick-reference content.
|
|
43529
|
-
*
|
|
43530
|
-
* @private internal utility of `ptbk coder`
|
|
43531
|
-
*/
|
|
43532
|
-
function getDefaultCoderAgentCodingFileContent({ packageJsonScripts, }) {
|
|
43533
|
-
return spaceTrim$1((block) => `
|
|
43534
|
-
# Promptbook Coder quick reference
|
|
43535
|
-
|
|
43536
|
-
This project is prepared for the \`ptbk coder\` workflow. Promptbook Coder does not create a new model on its own; it orchestrates coding agents such as GitHub Copilot, OpenAI Codex, Claude Code, Opencode, Cline, and Gemini CLI through prompt files in \`${formatDisplayPath(PROMPTS_DIRECTORY_PATH)}/\`.
|
|
43537
|
-
|
|
43538
|
-
## Workflow
|
|
43539
|
-
1. Put repository-wide coding rules into \`${AGENTS_FILE_PATH}\`. The default \`npm run coder:run\` script already passes \`--context ${AGENTS_FILE_PATH}\`.
|
|
43540
|
-
2. Create or customize prompt templates in \`${formatDisplayPath(PROMPTS_TEMPLATES_DIRECTORY_PATH)}/\`. ${buildStarterTemplateSentence()}
|
|
43541
|
-
3. Generate prompt files with \`npm run coder:generate-boilerplates\` or \`ptbk coder generate-boilerplates --template <template> --count <count>\`. To append a single ready-to-run prompt straight from a description, use \`npm run coder:add\` or \`ptbk coder add "some new feature"\`.
|
|
43542
|
-
4. Replace every \`@@@\`, keep drafts as \`[-]\`, and switch prompts to \`[ ]\` when they are ready to run. Completed prompts are marked \`[x]\`.
|
|
43543
|
-
5. Run \`npm run coder:run\` to execute the next ready prompt with the configured coding agent.
|
|
43544
|
-
6. Use \`npm run coder:verify\` to archive finished prompts into \`${formatDisplayPath(PROMPTS_DONE_DIRECTORY_PATH)}/\` and append repair follow-up prompts when more work is needed.
|
|
43545
|
-
7. Use \`ptbk coder find-refactor-candidates\` when you want Promptbook to suggest refactor prompts automatically.
|
|
43546
|
-
|
|
43547
|
-
## Templates
|
|
43548
|
-
- Project-owned templates created by \`ptbk coder init\`: ${formatInlineCodeList(getDefaultCoderProjectPromptTemplateDefinitions().map(({ relativeFilePath }) => formatDisplayPath(relativeFilePath)))}
|
|
43549
|
-
- Built-in \`--template\` aliases: ${formatInlineCodeList(getDefaultCoderPromptTemplateDefinitions().map(({ id }) => id))}
|
|
43550
|
-
- To add a custom template, create a markdown file such as \`${formatDisplayPath(PROMPTS_TEMPLATES_DIRECTORY_PATH)}/backend.md\`.
|
|
43551
|
-
- To use a project template, run \`ptbk coder generate-boilerplates --template ${formatDisplayPath(PROMPTS_TEMPLATES_DIRECTORY_PATH)}/backend.md\`.
|
|
43552
|
-
- Keep shared repository rules in \`${AGENTS_FILE_PATH}\` and recurring task-family rules in template files so individual prompt files stay focused on the actual task.
|
|
43553
|
-
|
|
43554
|
-
## Created npm scripts
|
|
43555
|
-
| Script | Purpose |
|
|
43556
|
-
| --- | --- |
|
|
43557
|
-
${block(buildPackageJsonScriptTableLines(packageJsonScripts).join('\n'))}
|
|
43558
|
-
|
|
43559
|
-
## Customizing the workflow
|
|
43560
|
-
- Edit \`package.json\` if you want \`npm run coder:run\` to use another coding agent, model, thinking level, context file, or wait mode.
|
|
43561
|
-
- Use direct CLI commands when you need one-off flags such as \`--min-priority\`, \`--max-priority\`, \`--ignore-git-changes\`, \`--no-commit\`, \`--dry-run\`, \`--test\`, \`--allow-credits\`, or \`--auto-migrate\`.
|
|
43562
|
-
- Use \`ptbk coder --help\` and \`ptbk coder <command> --help\` for the full CLI reference.
|
|
43563
|
-
`);
|
|
43564
|
-
}
|
|
43565
|
-
/**
|
|
43566
|
-
* Builds the sentence describing the starter templates created during initialization.
|
|
43567
|
-
*/
|
|
43568
|
-
function buildStarterTemplateSentence() {
|
|
43569
|
-
const starterTemplatePaths = getDefaultCoderProjectPromptTemplateDefinitions().map(({ relativeFilePath }) => formatDisplayPath(relativeFilePath));
|
|
43570
|
-
if (starterTemplatePaths.length === 1) {
|
|
43571
|
-
return `The starter project template created by \`ptbk coder init\` is \`${starterTemplatePaths[0]}\`.`;
|
|
43572
|
-
}
|
|
43573
|
-
return `The starter project templates created by \`ptbk coder init\` are ${formatInlineCodeList(starterTemplatePaths)}.`;
|
|
43574
|
-
}
|
|
43575
|
-
/**
|
|
43576
|
-
* Builds the markdown table rows describing the initialized npm scripts.
|
|
43577
|
-
*/
|
|
43578
|
-
function buildPackageJsonScriptTableLines(packageJsonScripts) {
|
|
43579
|
-
return Object.entries(packageJsonScripts).map(([scriptName, scriptCommand]) => `| \`npm run ${scriptName}\` | ${describeDefaultCoderPackageJsonScript(scriptName, scriptCommand)} |`);
|
|
43580
|
-
}
|
|
43581
|
-
/**
|
|
43582
|
-
* Describes one initialized npm script in human-readable terms.
|
|
43583
|
-
*/
|
|
43584
|
-
function describeDefaultCoderPackageJsonScript(scriptName, scriptCommand) {
|
|
43585
|
-
if (scriptName === 'coder:generate-boilerplates') {
|
|
43586
|
-
return `Runs \`${scriptCommand}\` to create new prompt files in \`${formatDisplayPath(PROMPTS_DIRECTORY_PATH)}/\`.`;
|
|
43587
|
-
}
|
|
43588
|
-
if (scriptName === 'coder:add') {
|
|
43589
|
-
return `Runs \`${scriptCommand}\` to add one ready-to-run prompt file to \`${formatDisplayPath(PROMPTS_DIRECTORY_PATH)}/\` from a plain-language description.`;
|
|
43590
|
-
}
|
|
43591
|
-
if (scriptName === 'coder:run') {
|
|
43592
|
-
return `Runs \`${scriptCommand}\` to execute the next ready prompt with shared repository context from \`${AGENTS_FILE_PATH}\`.`;
|
|
43593
|
-
}
|
|
43594
|
-
if (scriptName === 'coder:find-refactor-candidates') {
|
|
43595
|
-
return `Runs \`${scriptCommand}\` to generate prompt candidates for large or crowded files.`;
|
|
43596
|
-
}
|
|
43597
|
-
if (scriptName === 'coder:verify') {
|
|
43598
|
-
return `Runs \`${scriptCommand}\` to archive verified prompts into \`${formatDisplayPath(PROMPTS_DONE_DIRECTORY_PATH)}/\` and append repair prompts when needed.`;
|
|
43599
|
-
}
|
|
43600
|
-
return `Runs \`${scriptCommand}\`.`;
|
|
43601
|
-
}
|
|
43602
|
-
/**
|
|
43603
|
-
* Formats one inline code list for human-readable markdown.
|
|
43604
|
-
*/
|
|
43605
|
-
function formatInlineCodeList(values) {
|
|
43606
|
-
return values.map((value) => `\`${value}\``).join(', ');
|
|
43607
|
-
}
|
|
43608
|
-
// Note: [🟡] Code for coder AGENT_CODING file boilerplate [agentCodingFile](src/cli/cli-commands/coder/agentCodingFile.ts) should never be published outside of `@promptbook/cli`
|
|
43609
|
-
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
43610
|
-
|
|
43611
43669
|
/**
|
|
43612
43670
|
* Relative directory path for agents initialized by `ptbk coder init`.
|
|
43613
43671
|
*
|
|
@@ -43672,6 +43730,16 @@ async function isExistingFile$2(path) {
|
|
|
43672
43730
|
}
|
|
43673
43731
|
// Note: [🟡] Code for coder init developer agent bootstrapping [ensureCoderDeveloperAgentFile](src/cli/cli-commands/coder/ensureCoderDeveloperAgentFile.ts) should never be published outside of `@promptbook/cli`
|
|
43674
43732
|
|
|
43733
|
+
/**
|
|
43734
|
+
* Normalizes one project-relative path for human-readable CLI output and markdown.
|
|
43735
|
+
*
|
|
43736
|
+
* @private internal utility of `ptbk coder`
|
|
43737
|
+
*/
|
|
43738
|
+
function formatDisplayPath(relativePath) {
|
|
43739
|
+
return relativePath.replace(/\\/gu, '/');
|
|
43740
|
+
}
|
|
43741
|
+
// Note: [🟡] Code for coder path formatting [formatDisplayPath](src/cli/cli-commands/coder/formatDisplayPath.ts) should never be published outside of `@promptbook/cli`
|
|
43742
|
+
|
|
43675
43743
|
/**
|
|
43676
43744
|
* Fallback `.env` content used when no required variables need to be appended.
|
|
43677
43745
|
*/
|
|
@@ -43749,7 +43817,7 @@ async function ensureCoderGitignoreFile(projectPath) {
|
|
|
43749
43817
|
const DEFAULT_CODER_PACKAGE_JSON_SCRIPTS = {
|
|
43750
43818
|
'coder:generate-boilerplates': 'ptbk coder generate-boilerplates --template ./prompts/templates/common.md',
|
|
43751
43819
|
'coder:add': 'ptbk coder add --template ./prompts/templates/common.md',
|
|
43752
|
-
'coder:run': 'ptbk coder run --harness openai-codex --model gpt-5.
|
|
43820
|
+
'coder:run': 'ptbk coder run --harness openai-codex --model gpt-5.6-terra --thinking-level max --agent agents/developer.book --context AGENTS.md --test-before yes-and-fix',
|
|
43753
43821
|
// 'coder:find-refactor-candidates': 'npx ptbk coder find-refactor-candidates',
|
|
43754
43822
|
'coder:verify': 'ptbk coder verify',
|
|
43755
43823
|
};
|
|
@@ -43998,9 +44066,7 @@ async function initializeCoderProjectConfiguration(projectPath) {
|
|
|
43998
44066
|
const agentsDirectoryStatus = await ensureDirectory(projectPath, CODER_AGENTS_DIRECTORY_PATH);
|
|
43999
44067
|
const developerAgentFileStatus = await ensureCoderDeveloperAgentFile(projectPath);
|
|
44000
44068
|
const agentsFileStatus = await ensureCoderMarkdownFile(projectPath, AGENTS_FILE_PATH, getDefaultCoderAgentsFileContent());
|
|
44001
|
-
const agentCodingFileStatus = await ensureCoderMarkdownFile(projectPath, AGENT_CODING_FILE_PATH, getDefaultCoderAgentCodingFileContent(
|
|
44002
|
-
packageJsonScripts: getDefaultCoderPackageJsonScripts(),
|
|
44003
|
-
}));
|
|
44069
|
+
const agentCodingFileStatus = await ensureCoderMarkdownFile(projectPath, AGENT_CODING_FILE_PATH, getDefaultCoderAgentCodingFileContent());
|
|
44004
44070
|
const { envFileStatus, initializedEnvVariableNames } = await ensureCoderEnvFile(projectPath);
|
|
44005
44071
|
const gitignoreFileStatus = await ensureCoderGitignoreFile(projectPath);
|
|
44006
44072
|
const packageJsonFileStatus = await ensureCoderPackageJsonFile(projectPath);
|
|
@@ -44115,12 +44181,24 @@ function $initializeCoderInitCommand(program) {
|
|
|
44115
44181
|
|
|
44116
44182
|
Checks that the coding harnesses are installed globally and up to date:
|
|
44117
44183
|
${block(listCheckedHarnessLabels())}
|
|
44184
|
+
|
|
44185
|
+
${block(CODER_GIT_SYNC_DESCRIPTION)}
|
|
44118
44186
|
`));
|
|
44119
|
-
command
|
|
44187
|
+
addCoderGitSyncOptions(command);
|
|
44188
|
+
command.action(handleActionErrors(async (cliOptions) => {
|
|
44189
|
+
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
44120
44190
|
const projectPath = process.cwd();
|
|
44191
|
+
// Note: Import the git synchronization dynamically to keep the CLI fast for runs without `--commit`
|
|
44192
|
+
const { $commitCoderChanges, $pullCoderChanges } = await Promise.resolve().then(function () { return coderGitSync; });
|
|
44193
|
+
await $pullCoderChanges({ gitSync, projectPath });
|
|
44121
44194
|
const summary = await initializeCoderProjectConfiguration(projectPath);
|
|
44122
44195
|
printInitializationSummary(summary);
|
|
44123
44196
|
await generatePromptBoilerplate({ projectPath, filesCount: 5 });
|
|
44197
|
+
await $commitCoderChanges({
|
|
44198
|
+
gitSync,
|
|
44199
|
+
projectPath,
|
|
44200
|
+
commitMessage: 'Initialize Promptbook Coder',
|
|
44201
|
+
});
|
|
44124
44202
|
await $ensureHarnessInstallations(CODER_INIT_CHECKED_HARNESS_NAMES);
|
|
44125
44203
|
}));
|
|
44126
44204
|
}
|
|
@@ -44141,6 +44219,48 @@ function listDefaultCoderProjectPromptTemplateDisplayPaths() {
|
|
|
44141
44219
|
// Note: [🟡] Code for CLI command [init](src/cli/cli-commands/coder/init.ts) should never be published outside of `@promptbook/cli`
|
|
44142
44220
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
44143
44221
|
|
|
44222
|
+
/**
|
|
44223
|
+
* Initializes `coder ping` command for Promptbook CLI utilities
|
|
44224
|
+
*
|
|
44225
|
+
* Note: `$` is used to indicate that this function is not a pure function - it registers a command in the CLI
|
|
44226
|
+
*
|
|
44227
|
+
* @private internal function of `promptbookCli`
|
|
44228
|
+
*/
|
|
44229
|
+
function $initializeCoderPingCommand(program) {
|
|
44230
|
+
const command = program.command('ping');
|
|
44231
|
+
command.description(spaceTrim$1(`
|
|
44232
|
+
Send one tiny dummy prompt to a harness and model to measure and warm them up
|
|
44233
|
+
|
|
44234
|
+
${PROMPT_RUNNER_DESCRIPTION}
|
|
44235
|
+
|
|
44236
|
+
Features:
|
|
44237
|
+
- Verifies that the selected harness, model, thinking level and authentication really work
|
|
44238
|
+
- Reports the answer of the harness, the response time and the reported usage
|
|
44239
|
+
- Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
|
|
44240
|
+
- Leaves the project exactly as it was — nothing is read, written, changed or committed
|
|
44241
|
+
- Use --no-ui to stream the raw harness output instead of only the compact result
|
|
44242
|
+
`));
|
|
44243
|
+
addPromptRunnerSelectionOptions(command);
|
|
44244
|
+
addPromptRunnerRuntimeOptions(command);
|
|
44245
|
+
command.action(handleActionErrors(async (cliOptions) => {
|
|
44246
|
+
const runnerOptions = normalizePromptRunnerSelectionCliOptions(cliOptions, { isAgentRequired: true });
|
|
44247
|
+
await $ensureHarnessInstallations([runnerOptions.agentName]);
|
|
44248
|
+
// Note: Import the ping dynamically to avoid loading heavy dependencies until needed
|
|
44249
|
+
const { pingCoderHarness } = await Promise.resolve().then(function () { return pingCoderHarness$1; });
|
|
44250
|
+
const { printCoderPingResult } = await Promise.resolve().then(function () { return printCoderPingResult$1; });
|
|
44251
|
+
const result = await pingCoderHarness({
|
|
44252
|
+
agentName: runnerOptions.agentName,
|
|
44253
|
+
model: runnerOptions.model,
|
|
44254
|
+
thinkingLevel: runnerOptions.thinkingLevel,
|
|
44255
|
+
allowCredits: runnerOptions.allowCredits,
|
|
44256
|
+
shouldPrintLiveOutput: runnerOptions.noUi,
|
|
44257
|
+
});
|
|
44258
|
+
printCoderPingResult(result);
|
|
44259
|
+
}));
|
|
44260
|
+
}
|
|
44261
|
+
// Note: [🟡] Code for CLI command [ping](src/cli/cli-commands/coder/ping.ts) should never be published outside of `@promptbook/cli`
|
|
44262
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
44263
|
+
|
|
44144
44264
|
/**
|
|
44145
44265
|
* Creates a Commander argument parser that accepts only non-negative integers.
|
|
44146
44266
|
*
|
|
@@ -44165,6 +44285,21 @@ function createNonNegativeIntegerOptionParser(optionName) {
|
|
|
44165
44285
|
}
|
|
44166
44286
|
// Note: [🟡] Code for CLI option parser [createNonNegativeIntegerOptionParser](src/cli/cli-commands/common/createNonNegativeIntegerOptionParser.ts) should never be published outside of `@promptbook/cli`
|
|
44167
44287
|
|
|
44288
|
+
/**
|
|
44289
|
+
* Modes supported by `ptbk coder run --test-before`.
|
|
44290
|
+
*/
|
|
44291
|
+
const TEST_BEFORE_MODE_VALUES = ['no', 'yes-and-fail', 'yes-and-fix'];
|
|
44292
|
+
/**
|
|
44293
|
+
* Default verification command used when a pre-coding mode is enabled without an explicit `--test` command.
|
|
44294
|
+
*/
|
|
44295
|
+
const DEFAULT_CODER_TEST_COMMAND = 'npm test';
|
|
44296
|
+
/**
|
|
44297
|
+
* Checks whether a value is a supported `--test-before` mode.
|
|
44298
|
+
*/
|
|
44299
|
+
function isTestBeforeMode(value) {
|
|
44300
|
+
return TEST_BEFORE_MODE_VALUES.includes(value);
|
|
44301
|
+
}
|
|
44302
|
+
|
|
44168
44303
|
/**
|
|
44169
44304
|
* Default wait duration applied before retrying a prompt round after an error (10 minutes).
|
|
44170
44305
|
*
|
|
@@ -44209,6 +44344,7 @@ function $initializeCoderRunCommand(program) {
|
|
|
44209
44344
|
- Optional --no-ui keeps plain streaming console output for logging and debugging
|
|
44210
44345
|
- Checks that the selected harness is installed globally and up to date before the first prompt
|
|
44211
44346
|
- Supports GPG signing of commits
|
|
44347
|
+
- Optional pre-coding test run that can stop or repair pre-existing failures
|
|
44212
44348
|
- Optional post-prompt verification with test-feedback retries
|
|
44213
44349
|
- Progress tracking and interactive P/S/X terminal controls
|
|
44214
44350
|
- Dry-run mode to preview prompts
|
|
@@ -44218,6 +44354,9 @@ function $initializeCoderRunCommand(program) {
|
|
|
44218
44354
|
command.option('--agent <agent-book-path>', 'Path to a .book file whose compiled system message is prepended to each coding prompt');
|
|
44219
44355
|
command.option('--context <context-or-file>', 'Append extra instructions either inline or from a file path relative to the current project');
|
|
44220
44356
|
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
44357
|
+
command.addOption(new Option('--test-before <mode>', `Run tests before coding: ${TEST_BEFORE_MODE_VALUES.join(', ')} (defaults to no; uses npm test when --test is omitted)`)
|
|
44358
|
+
.choices([...TEST_BEFORE_MODE_VALUES])
|
|
44359
|
+
.default('no'));
|
|
44221
44360
|
command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
|
|
44222
44361
|
addPromptRunnerExecutionOptions(command);
|
|
44223
44362
|
command.option('--isolate', spaceTrim$1(`
|
|
@@ -44247,8 +44386,9 @@ function $initializeCoderRunCommand(program) {
|
|
|
44247
44386
|
command.option('--auto-migrate', 'Run testing-server database migrations automatically after each successfully processed prompt');
|
|
44248
44387
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
44249
44388
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
44250
|
-
const { dryRun, agent, context, test, preserveLogs, isolate: isIsolated, priority, minPriority: minimumPriority, maxPriority: maximumPriority, limit, waitAfterPrompt: waitAfterPromptValue, waitBetweenPrompts: waitBetweenPromptsValue, waitAfterError: waitAfterErrorValue, auto, autoMigrate, allowDestructiveAutoMigrate, } = cliOptions;
|
|
44251
|
-
const
|
|
44389
|
+
const { dryRun, agent, context, test, testBefore, preserveLogs, isolate: isIsolated, priority, minPriority: minimumPriority, maxPriority: maximumPriority, limit, waitAfterPrompt: waitAfterPromptValue, waitBetweenPrompts: waitBetweenPromptsValue, waitAfterError: waitAfterErrorValue, auto, autoMigrate, allowDestructiveAutoMigrate, } = cliOptions;
|
|
44390
|
+
const configuredTestCommand = normalizeCommandOptionValue$1(test);
|
|
44391
|
+
const testCommand = configuredTestCommand !== null && configuredTestCommand !== void 0 ? configuredTestCommand : (testBefore === 'no' ? undefined : DEFAULT_CODER_TEST_COMMAND);
|
|
44252
44392
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
44253
44393
|
isAgentRequired: !dryRun,
|
|
44254
44394
|
});
|
|
@@ -44277,6 +44417,7 @@ function $initializeCoderRunCommand(program) {
|
|
|
44277
44417
|
agent,
|
|
44278
44418
|
context,
|
|
44279
44419
|
testCommand,
|
|
44420
|
+
testBefore,
|
|
44280
44421
|
preserveLogs,
|
|
44281
44422
|
isIsolated,
|
|
44282
44423
|
noUi: runnerOptions.noUi,
|
|
@@ -44487,25 +44628,31 @@ function normalizeCommandOptionValue(value) {
|
|
|
44487
44628
|
*/
|
|
44488
44629
|
function $initializeCoderVerifyCommand(program) {
|
|
44489
44630
|
const command = program.command('verify');
|
|
44490
|
-
command.description(spaceTrim$1(`
|
|
44491
|
-
|
|
44631
|
+
command.description(spaceTrim$1((block) => `
|
|
44632
|
+
Interactive verification helper for completed prompts
|
|
44492
44633
|
|
|
44493
|
-
|
|
44494
|
-
|
|
44495
|
-
|
|
44496
|
-
|
|
44497
|
-
|
|
44498
|
-
|
|
44499
|
-
|
|
44500
|
-
|
|
44634
|
+
Features:
|
|
44635
|
+
- Displays list of prompt files with status counts
|
|
44636
|
+
- Guides through verification of completed prompts marked [x]
|
|
44637
|
+
- Archives verified prompt files to prompts/done/ directory
|
|
44638
|
+
- Auto-appends repair prompts for incomplete work
|
|
44639
|
+
- Processes files with all-done prompts first
|
|
44640
|
+
- Supports ignoring matching prompt candidates for one verification run
|
|
44641
|
+
|
|
44642
|
+
${block(CODER_GIT_SYNC_DESCRIPTION)}
|
|
44643
|
+
|
|
44644
|
+
Note: The git synchronization is applied around each single verification, not once per run.
|
|
44645
|
+
`));
|
|
44501
44646
|
command.option('--reverse', 'Process prompt files in reverse order', false);
|
|
44502
44647
|
command.option('--ignore <candidate-text>', 'Ignore prompt files whose filename or first prompt line contains the given text (repeatable)', collectStringOption, []);
|
|
44648
|
+
addCoderGitSyncOptions(command);
|
|
44503
44649
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
44504
44650
|
const { reverse, ignore } = cliOptions;
|
|
44651
|
+
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
44505
44652
|
// Note: Import the main function dynamically to avoid loading heavy dependencies until needed
|
|
44506
44653
|
const { verifyPrompts } = await Promise.resolve().then(function () { return verifyPrompts$1; });
|
|
44507
44654
|
try {
|
|
44508
|
-
await verifyPrompts({ reverse, ignore });
|
|
44655
|
+
await verifyPrompts({ reverse, ignore, gitSync });
|
|
44509
44656
|
}
|
|
44510
44657
|
catch (error) {
|
|
44511
44658
|
console.error(colors.bgRed('Prompt verification failed:'), error);
|
|
@@ -44534,6 +44681,7 @@ function collectStringOption(value, previousValues) {
|
|
|
44534
44681
|
* - generate-boilerplates: Generate prompt boilerplate files
|
|
44535
44682
|
* - find-refactor-candidates: Find files that need refactoring
|
|
44536
44683
|
* - run: Run coding prompts with AI agents
|
|
44684
|
+
* - ping: Test one harness and model with a tiny dummy prompt
|
|
44537
44685
|
* - verify: Verify completed prompts
|
|
44538
44686
|
* - find-fresh-emoji-tags: Find unused emoji tags
|
|
44539
44687
|
*
|
|
@@ -44553,6 +44701,7 @@ function $initializeCoderCommand(program) {
|
|
|
44553
44701
|
- find-refactor-candidates: Find files that need refactoring
|
|
44554
44702
|
- find-unwritten: List prompt sections that still need to be authored
|
|
44555
44703
|
- run: Run coding prompts with AI agents
|
|
44704
|
+
- ping: Test the connection, response time and quota of one harness and model
|
|
44556
44705
|
- server: Start a long-running coder server with a kanban web UI
|
|
44557
44706
|
- verify: Verify completed prompts
|
|
44558
44707
|
- find-fresh-emoji-tags: Find unused emoji tags
|
|
@@ -44564,6 +44713,7 @@ function $initializeCoderCommand(program) {
|
|
|
44564
44713
|
$initializeCoderFindRefactorCandidatesCommand(coderCommand);
|
|
44565
44714
|
$initializeCoderFindUnwrittenCommand(coderCommand);
|
|
44566
44715
|
$initializeCoderRunCommand(coderCommand);
|
|
44716
|
+
$initializeCoderPingCommand(coderCommand);
|
|
44567
44717
|
$initializeCoderServerCommand(coderCommand);
|
|
44568
44718
|
$initializeCoderVerifyCommand(coderCommand);
|
|
44569
44719
|
$initializeCoderFindFreshEmojiTagCommand(coderCommand);
|
|
@@ -45397,6 +45547,14 @@ class FileCacheStorage {
|
|
|
45397
45547
|
// Note: [🟢] Code for Node file-cache storage [FileCacheStorage](src/storage/file-cache-storage/FileCacheStorage.ts) should never be published into packages that could be imported into browser environment
|
|
45398
45548
|
// TODO: [🌗] Maybe some checkers, not all valid JSONs are desired and valid values
|
|
45399
45549
|
|
|
45550
|
+
/**
|
|
45551
|
+
* Loads the Socket.io client (`socket.io-client`) on demand
|
|
45552
|
+
*
|
|
45553
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast
|
|
45554
|
+
*
|
|
45555
|
+
* @private internal utility of `createRemoteClient`
|
|
45556
|
+
*/
|
|
45557
|
+
const loadSocketIoClientModule = createLazyModuleLoader(() => import('socket.io-client'));
|
|
45400
45558
|
/**
|
|
45401
45559
|
* Creates a connection to the remote proxy server.
|
|
45402
45560
|
*
|
|
@@ -45425,6 +45583,7 @@ async function createRemoteClient(options) {
|
|
|
45425
45583
|
|
|
45426
45584
|
`));
|
|
45427
45585
|
}
|
|
45586
|
+
const { io } = await loadSocketIoClientModule();
|
|
45428
45587
|
return new Promise((resolve, reject) => {
|
|
45429
45588
|
const socket = io(remoteServerUrl, {
|
|
45430
45589
|
retries: CONNECTION_RETRIES_LIMIT,
|
|
@@ -46092,6 +46251,7 @@ async function $provideLlmToolsForCli(options) {
|
|
|
46092
46251
|
You will be logged in to ${remoteServerUrl}
|
|
46093
46252
|
If you don't have an account, it will be created automatically.
|
|
46094
46253
|
`)));
|
|
46254
|
+
const { default: prompts } = await loadPromptsModule();
|
|
46095
46255
|
const { username, password } = await prompts([
|
|
46096
46256
|
{
|
|
46097
46257
|
type: 'text',
|
|
@@ -46467,6 +46627,15 @@ function $initializeLoginCommand(program) {
|
|
|
46467
46627
|
// TODO: Implement non-interactive login
|
|
46468
46628
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
46469
46629
|
|
|
46630
|
+
/**
|
|
46631
|
+
* Loads the ZIP archive library (`jszip`) on demand
|
|
46632
|
+
*
|
|
46633
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast
|
|
46634
|
+
*
|
|
46635
|
+
* @private internal utility of `loadArchive` and `saveArchive`
|
|
46636
|
+
*/
|
|
46637
|
+
const loadJsZipModule = createLazyModuleLoader(() => import('jszip'));
|
|
46638
|
+
|
|
46470
46639
|
/**
|
|
46471
46640
|
* Loads the books from the archive file with `.bookc` extension
|
|
46472
46641
|
*
|
|
@@ -46481,6 +46650,7 @@ async function loadArchive(filePath, fs) {
|
|
|
46481
46650
|
throw new UnexpectedError(`Archive file must have '.bookc' extension`);
|
|
46482
46651
|
}
|
|
46483
46652
|
const data = await fs.readFile(filePath);
|
|
46653
|
+
const { default: JSZip } = await loadJsZipModule();
|
|
46484
46654
|
const archive = await JSZip.loadAsync(data);
|
|
46485
46655
|
const indexFile = archive.file('index.book.json');
|
|
46486
46656
|
if (!indexFile) {
|
|
@@ -50544,7 +50714,23 @@ function createShowdownConverter() {
|
|
|
50544
50714
|
});
|
|
50545
50715
|
}
|
|
50546
50716
|
|
|
50547
|
-
|
|
50717
|
+
/**
|
|
50718
|
+
* Loads `jsdom` on demand
|
|
50719
|
+
*
|
|
50720
|
+
* Note: [🐌] `jsdom` is by far the heaviest dependency of Promptbook, loading it eagerly would slow down every single
|
|
50721
|
+
* run of the `ptbk` CLI utility even when no website is scraped
|
|
50722
|
+
*
|
|
50723
|
+
* @private internal utility of `WebsiteScraper`
|
|
50724
|
+
*/
|
|
50725
|
+
const loadJsdomModule = createLazyModuleLoader(() => import('jsdom'));
|
|
50726
|
+
/**
|
|
50727
|
+
* Loads `@mozilla/readability` on demand
|
|
50728
|
+
*
|
|
50729
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast
|
|
50730
|
+
*
|
|
50731
|
+
* @private internal utility of `WebsiteScraper`
|
|
50732
|
+
*/
|
|
50733
|
+
const loadReadabilityModule = createLazyModuleLoader(() => import('@mozilla/readability'));
|
|
50548
50734
|
/**
|
|
50549
50735
|
* Scraper for websites
|
|
50550
50736
|
*
|
|
@@ -50580,6 +50766,7 @@ class WebsiteScraper {
|
|
|
50580
50766
|
if (this.tools.fs === undefined) {
|
|
50581
50767
|
throw new EnvironmentMismatchError('Can not scrape websites without filesystem tools');
|
|
50582
50768
|
}
|
|
50769
|
+
const [{ JSDOM }, { Readability }] = await Promise.all([loadJsdomModule(), loadReadabilityModule()]);
|
|
50583
50770
|
const jsdom = new JSDOM(await source.asText(), {
|
|
50584
50771
|
url: source.url,
|
|
50585
50772
|
});
|
|
@@ -54183,6 +54370,7 @@ async function saveArchive(filePath, collectionJson, fs) {
|
|
|
54183
54370
|
for (const pipelineJson of collectionJson) {
|
|
54184
54371
|
validatePipeline(pipelineJson);
|
|
54185
54372
|
}
|
|
54373
|
+
const { default: JSZip } = await loadJsZipModule();
|
|
54186
54374
|
const archive = new JSZip();
|
|
54187
54375
|
const collectionJsonString = stringifyPipelineJson(collectionJson);
|
|
54188
54376
|
archive.file('index.book.json', collectionJsonString);
|
|
@@ -54811,6 +54999,7 @@ async function runInteractiveChatbot(options) {
|
|
|
54811
54999
|
else {
|
|
54812
55000
|
console.info(colors.gray(`---`));
|
|
54813
55001
|
}
|
|
55002
|
+
const { default: prompts } = await loadPromptsModule();
|
|
54814
55003
|
const response = await prompts({
|
|
54815
55004
|
type: 'text',
|
|
54816
55005
|
name: 'userMessage',
|
|
@@ -55118,6 +55307,7 @@ async function resolveRunPipelineSource(pipelineSource) {
|
|
|
55118
55307
|
if (pipelineSource) {
|
|
55119
55308
|
return pipelineSource;
|
|
55120
55309
|
}
|
|
55310
|
+
const { default: prompts } = await loadPromptsModule();
|
|
55121
55311
|
const response = await prompts({
|
|
55122
55312
|
type: 'text',
|
|
55123
55313
|
name: 'pipelineSource',
|
|
@@ -55205,6 +55395,7 @@ async function resolveRunInputParameters(options) {
|
|
|
55205
55395
|
console.error(colors.red(createRunMissingInputParametersMessage(pipeline, inputParameters, questions)));
|
|
55206
55396
|
return process.exit(1);
|
|
55207
55397
|
}
|
|
55398
|
+
const { default: prompts } = await loadPromptsModule();
|
|
55208
55399
|
const response = await prompts(questions);
|
|
55209
55400
|
// <- TODO: [🧠][🍼] Change behavior according to the formfactor
|
|
55210
55401
|
return { ...inputParameters, ...response };
|
|
@@ -58110,6 +58301,14 @@ const ANTHROPIC_PROVIDER_PROFILE = {
|
|
|
58110
58301
|
fullname: 'Anthropic Claude',
|
|
58111
58302
|
color: '#d97706',
|
|
58112
58303
|
};
|
|
58304
|
+
/**
|
|
58305
|
+
* Loads the Anthropic Claude SDK (`@anthropic-ai/sdk`) on demand
|
|
58306
|
+
*
|
|
58307
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast
|
|
58308
|
+
*
|
|
58309
|
+
* @private internal utility of `AnthropicClaudeExecutionTools`
|
|
58310
|
+
*/
|
|
58311
|
+
const loadAnthropicClaudeModule = createLazyModuleLoader(() => import('@anthropic-ai/sdk'));
|
|
58113
58312
|
/**
|
|
58114
58313
|
* Execution Tools for calling Anthropic Claude API.
|
|
58115
58314
|
*
|
|
@@ -58147,6 +58346,7 @@ class AnthropicClaudeExecutionTools {
|
|
|
58147
58346
|
const anthropicOptions = { ...this.options };
|
|
58148
58347
|
delete anthropicOptions.isVerbose;
|
|
58149
58348
|
delete anthropicOptions.isProxied;
|
|
58349
|
+
const { Anthropic } = await loadAnthropicClaudeModule();
|
|
58150
58350
|
this.client = new Anthropic(anthropicOptions);
|
|
58151
58351
|
}
|
|
58152
58352
|
return this.client;
|
|
@@ -58410,6 +58610,14 @@ const AZURE_OPENAI_PROVIDER_PROFILE = {
|
|
|
58410
58610
|
fullname: 'Azure OpenAI',
|
|
58411
58611
|
color: '#0078d4',
|
|
58412
58612
|
};
|
|
58613
|
+
/**
|
|
58614
|
+
* Loads the Azure OpenAI SDK (`@azure/openai`) on demand
|
|
58615
|
+
*
|
|
58616
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast
|
|
58617
|
+
*
|
|
58618
|
+
* @private internal utility of `AzureOpenAiExecutionTools`
|
|
58619
|
+
*/
|
|
58620
|
+
const loadAzureOpenAiModule = createLazyModuleLoader(() => import('@azure/openai'));
|
|
58413
58621
|
/**
|
|
58414
58622
|
* Execution Tools for calling Azure OpenAI API.
|
|
58415
58623
|
*
|
|
@@ -58443,6 +58651,7 @@ class AzureOpenAiExecutionTools {
|
|
|
58443
58651
|
}
|
|
58444
58652
|
async getClient() {
|
|
58445
58653
|
if (this.client === null) {
|
|
58654
|
+
const { AzureKeyCredential, OpenAIClient } = await loadAzureOpenAiModule();
|
|
58446
58655
|
this.client = new OpenAIClient(`https://${this.options.resourceName}.openai.azure.com/`, new AzureKeyCredential(this.options.apiKey));
|
|
58447
58656
|
}
|
|
58448
58657
|
return this.client;
|
|
@@ -60252,6 +60461,14 @@ class OpenAiCompatibleNonChatPromptCaller {
|
|
|
60252
60461
|
}
|
|
60253
60462
|
}
|
|
60254
60463
|
|
|
60464
|
+
/**
|
|
60465
|
+
* Loads the OpenAI SDK (`openai`) on demand
|
|
60466
|
+
*
|
|
60467
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast
|
|
60468
|
+
*
|
|
60469
|
+
* @private internal utility of `OpenAiCompatibleRequestManager`
|
|
60470
|
+
*/
|
|
60471
|
+
const loadOpenAiModule = createLazyModuleLoader(() => import('openai'));
|
|
60255
60472
|
/**
|
|
60256
60473
|
* Manages OpenAI-compatible client creation plus shared retry and rate-limit behavior.
|
|
60257
60474
|
*
|
|
@@ -60278,6 +60495,7 @@ class OpenAiCompatibleRequestManager {
|
|
|
60278
60495
|
timeout: API_REQUEST_TIMEOUT,
|
|
60279
60496
|
maxRetries: CONNECTION_RETRIES_LIMIT,
|
|
60280
60497
|
};
|
|
60498
|
+
const { default: OpenAI } = await loadOpenAiModule();
|
|
60281
60499
|
this.client = new OpenAI(enhancedOptions);
|
|
60282
60500
|
}
|
|
60283
60501
|
return this.client;
|
|
@@ -67991,6 +68209,7 @@ async function runAgentChat(options) {
|
|
|
67991
68209
|
if (options.isVerbose) {
|
|
67992
68210
|
console.info(colors.gray('Type "exit" or "quit" to end the chat.'));
|
|
67993
68211
|
}
|
|
68212
|
+
const { default: prompts } = await loadPromptsModule();
|
|
67994
68213
|
while (true) {
|
|
67995
68214
|
const response = await prompts({
|
|
67996
68215
|
type: 'text',
|
|
@@ -69204,6 +69423,16 @@ class OpenAiAgentKitExecutionToolsOutputTypeMapper {
|
|
|
69204
69423
|
}
|
|
69205
69424
|
}
|
|
69206
69425
|
|
|
69426
|
+
/**
|
|
69427
|
+
* Loads the OpenAI AgentKit SDK (`@openai/agents`) on demand
|
|
69428
|
+
*
|
|
69429
|
+
* Note: [🐌] The AgentKit SDK is one of the heaviest dependencies of Promptbook, loading it eagerly would slow down
|
|
69430
|
+
* every single run of the `ptbk` CLI utility even when no AgentKit agent is used
|
|
69431
|
+
*
|
|
69432
|
+
* @private internal utility of `@promptbook/openai`
|
|
69433
|
+
*/
|
|
69434
|
+
const loadOpenAiAgentsModule = createLazyModuleLoader(() => import('@openai/agents'));
|
|
69435
|
+
|
|
69207
69436
|
/**
|
|
69208
69437
|
* Constant for default model used for nested DeepSearch tool invocations.
|
|
69209
69438
|
*/
|
|
@@ -69257,8 +69486,9 @@ class OpenAiAgentKitExecutionToolsToolBuilder {
|
|
|
69257
69486
|
/**
|
|
69258
69487
|
* Builds the tool list for AgentKit, including hosted file search when applicable.
|
|
69259
69488
|
*/
|
|
69260
|
-
buildAgentKitTools(options) {
|
|
69489
|
+
async buildAgentKitTools(options) {
|
|
69261
69490
|
const { tools, vectorStoreId } = options;
|
|
69491
|
+
const { fileSearchTool, tool: agentKitTool } = await loadOpenAiAgentsModule();
|
|
69262
69492
|
const agentKitTools = [];
|
|
69263
69493
|
if (vectorStoreId) {
|
|
69264
69494
|
agentKitTools.push(fileSearchTool(vectorStoreId));
|
|
@@ -69269,11 +69499,11 @@ class OpenAiAgentKitExecutionToolsToolBuilder {
|
|
|
69269
69499
|
let scriptTools = null;
|
|
69270
69500
|
for (const toolDefinition of tools) {
|
|
69271
69501
|
if (this.isDeepSearchToolDefinition(toolDefinition)) {
|
|
69272
|
-
agentKitTools.push(this.createDeepSearchAgentKitTool(toolDefinition));
|
|
69502
|
+
agentKitTools.push(await this.createDeepSearchAgentKitTool(toolDefinition));
|
|
69273
69503
|
continue;
|
|
69274
69504
|
}
|
|
69275
69505
|
scriptTools !== null && scriptTools !== void 0 ? scriptTools : (scriptTools = this.resolveScriptTools());
|
|
69276
|
-
agentKitTools.push(
|
|
69506
|
+
agentKitTools.push(agentKitTool({
|
|
69277
69507
|
name: toolDefinition.name,
|
|
69278
69508
|
description: toolDefinition.description,
|
|
69279
69509
|
parameters: this.normalizeAgentKitToolParameters(toolDefinition.parameters),
|
|
@@ -69480,8 +69710,9 @@ class OpenAiAgentKitExecutionToolsToolBuilder {
|
|
|
69480
69710
|
/**
|
|
69481
69711
|
* Creates the native Agent SDK tool used for `USE DEEPSEARCH`.
|
|
69482
69712
|
*/
|
|
69483
|
-
createDeepSearchAgentKitTool(toolDefinition) {
|
|
69484
|
-
const
|
|
69713
|
+
async createDeepSearchAgentKitTool(toolDefinition) {
|
|
69714
|
+
const { Agent: AgentFromKit, webSearchTool } = await loadOpenAiAgentsModule();
|
|
69715
|
+
const deepSearchAgent = new AgentFromKit({
|
|
69485
69716
|
name: 'DeepSearch',
|
|
69486
69717
|
model: DEFAULT_DEEP_SEARCH_MODEL_NAME,
|
|
69487
69718
|
instructions: this.createDeepSearchAgentInstructions(toolDefinition.description),
|
|
@@ -69694,8 +69925,9 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
69694
69925
|
vectorStoreId,
|
|
69695
69926
|
});
|
|
69696
69927
|
}
|
|
69697
|
-
const
|
|
69698
|
-
const
|
|
69928
|
+
const { Agent: AgentFromKit } = await loadOpenAiAgentsModule();
|
|
69929
|
+
const agentKitTools = await this.buildAgentKitTools({ tools, vectorStoreId });
|
|
69930
|
+
const openAiAgentKitAgent = new AgentFromKit({
|
|
69699
69931
|
name,
|
|
69700
69932
|
model: this.agentKitModelName,
|
|
69701
69933
|
instructions: instructions || 'You are a helpful assistant.',
|
|
@@ -69740,6 +69972,7 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
69740
69972
|
agentName: agentForRun.name,
|
|
69741
69973
|
input: inputItems,
|
|
69742
69974
|
};
|
|
69975
|
+
const { run } = await loadOpenAiAgentsModule();
|
|
69743
69976
|
const streamResult = await run(agentForRun, inputItems, {
|
|
69744
69977
|
stream: true,
|
|
69745
69978
|
maxTurns: 200,
|
|
@@ -69882,6 +70115,7 @@ class OpenAiAgentKitExecutionTools extends OpenAiVectorStoreHandler {
|
|
|
69882
70115
|
* Ensures the AgentKit SDK is wired to the OpenAI client and API key.
|
|
69883
70116
|
*/
|
|
69884
70117
|
async ensureAgentKitDefaults() {
|
|
70118
|
+
const { setDefaultOpenAIClient, setDefaultOpenAIKey } = await loadOpenAiAgentsModule();
|
|
69885
70119
|
const client = await this.getClient();
|
|
69886
70120
|
setDefaultOpenAIClient(client);
|
|
69887
70121
|
const apiKey = this.agentKitOptions.apiKey;
|
|
@@ -72214,6 +72448,66 @@ var RemoteAgent$1 = /*#__PURE__*/Object.freeze({
|
|
|
72214
72448
|
RemoteAgent: RemoteAgent
|
|
72215
72449
|
});
|
|
72216
72450
|
|
|
72451
|
+
/**
|
|
72452
|
+
* Git synchronization which leaves the repository completely untouched.
|
|
72453
|
+
*
|
|
72454
|
+
* Note: This is the default for every command and helper which supports the git synchronization.
|
|
72455
|
+
*/
|
|
72456
|
+
const DISABLED_CODER_GIT_SYNC_OPTIONS = Object.freeze({
|
|
72457
|
+
isCommitEnabled: false,
|
|
72458
|
+
isAutoPushEnabled: false,
|
|
72459
|
+
isAutoPullEnabled: false,
|
|
72460
|
+
});
|
|
72461
|
+
/**
|
|
72462
|
+
* Pulls the latest repository changes before a `ptbk coder` command changes the project.
|
|
72463
|
+
*/
|
|
72464
|
+
async function $pullCoderChanges(options) {
|
|
72465
|
+
const { gitSync, projectPath = process.cwd() } = options;
|
|
72466
|
+
if (!gitSync.isAutoPullEnabled) {
|
|
72467
|
+
return;
|
|
72468
|
+
}
|
|
72469
|
+
console.info(colors.gray('Pulling the latest changes from the remote repository...'));
|
|
72470
|
+
await pullLatestChanges(projectPath);
|
|
72471
|
+
}
|
|
72472
|
+
/**
|
|
72473
|
+
* Commits - and when requested also pushes - the changes one `ptbk coder` command has just made.
|
|
72474
|
+
*
|
|
72475
|
+
* Note: A repository without any change is left alone instead of creating an empty commit.
|
|
72476
|
+
*/
|
|
72477
|
+
async function $commitCoderChanges(options) {
|
|
72478
|
+
const { gitSync, commitMessage, projectPath = process.cwd() } = options;
|
|
72479
|
+
if (!gitSync.isCommitEnabled) {
|
|
72480
|
+
return;
|
|
72481
|
+
}
|
|
72482
|
+
if (!(await hasChangesToCommit(projectPath))) {
|
|
72483
|
+
console.info(colors.gray('Nothing to commit, the working tree is clean'));
|
|
72484
|
+
return;
|
|
72485
|
+
}
|
|
72486
|
+
await commitChanges(commitMessage, {
|
|
72487
|
+
projectPath,
|
|
72488
|
+
autoPush: gitSync.isAutoPushEnabled,
|
|
72489
|
+
});
|
|
72490
|
+
console.info(colors.green(`✓ ${gitSync.isAutoPushEnabled ? 'Committed and pushed' : 'Committed'}: ${commitMessage}`));
|
|
72491
|
+
}
|
|
72492
|
+
/**
|
|
72493
|
+
* Checks whether the repository holds any change which can be committed.
|
|
72494
|
+
*/
|
|
72495
|
+
async function hasChangesToCommit(projectPath) {
|
|
72496
|
+
const gitStatus = await runGitCommand({
|
|
72497
|
+
command: 'git status --porcelain',
|
|
72498
|
+
cwd: projectPath,
|
|
72499
|
+
isVerbose: false,
|
|
72500
|
+
});
|
|
72501
|
+
return gitStatus.trim() !== '';
|
|
72502
|
+
}
|
|
72503
|
+
|
|
72504
|
+
var coderGitSync = /*#__PURE__*/Object.freeze({
|
|
72505
|
+
__proto__: null,
|
|
72506
|
+
DISABLED_CODER_GIT_SYNC_OPTIONS: DISABLED_CODER_GIT_SYNC_OPTIONS,
|
|
72507
|
+
$pullCoderChanges: $pullCoderChanges,
|
|
72508
|
+
$commitCoderChanges: $commitCoderChanges
|
|
72509
|
+
});
|
|
72510
|
+
|
|
72217
72511
|
/**
|
|
72218
72512
|
* Calculates the next available prompt numbering sequence for a month.
|
|
72219
72513
|
*/
|
|
@@ -72688,6 +72982,31 @@ function normalizeRefactorCandidatePath(pathValue) {
|
|
|
72688
72982
|
}
|
|
72689
72983
|
// Note: [🟡] Code for repository script [normalizeRefactorCandidatePath](scripts/find-refactor-candidates/normalizeRefactorCandidatePath.ts) should never be published outside of `@promptbook/cli`
|
|
72690
72984
|
|
|
72985
|
+
/**
|
|
72986
|
+
* The TypeScript compiler API once it was loaded by `analyzeSourceFileForRefactorCandidate`
|
|
72987
|
+
*
|
|
72988
|
+
* Note: [🐌] `typescript` is a heavy package, it is loaded on demand so that it does not slow down every single run
|
|
72989
|
+
* of the `ptbk` CLI utility
|
|
72990
|
+
*
|
|
72991
|
+
* @private variable of analyzeSourceFileForRefactorCandidate
|
|
72992
|
+
*/
|
|
72993
|
+
let loadedTypescriptModule = null;
|
|
72994
|
+
/**
|
|
72995
|
+
* Returns the TypeScript compiler API which was already loaded for the structural analysis.
|
|
72996
|
+
*
|
|
72997
|
+
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72998
|
+
*/
|
|
72999
|
+
function getLoadedTypescriptModule() {
|
|
73000
|
+
if (loadedTypescriptModule === null) {
|
|
73001
|
+
throw new UnexpectedError(spaceTrim(`
|
|
73002
|
+
The \`typescript\` module was not loaded yet.
|
|
73003
|
+
|
|
73004
|
+
Structural analysis helpers must be called only from \`analyzeSourceFileForRefactorCandidate\` which
|
|
73005
|
+
loads \`typescript\` lazily.
|
|
73006
|
+
`));
|
|
73007
|
+
}
|
|
73008
|
+
return loadedTypescriptModule;
|
|
73009
|
+
}
|
|
72691
73010
|
/**
|
|
72692
73011
|
* Resolves whether a source file should produce a refactor candidate entry.
|
|
72693
73012
|
*
|
|
@@ -72713,6 +73032,7 @@ async function analyzeSourceFileForRefactorCandidate(options) {
|
|
|
72713
73032
|
}
|
|
72714
73033
|
}
|
|
72715
73034
|
if (STRUCTURAL_ANALYSIS_EXTENSIONS.includes(extension)) {
|
|
73035
|
+
loadedTypescriptModule !== null && loadedTypescriptModule !== void 0 ? loadedTypescriptModule : (loadedTypescriptModule = await getTypescriptModule());
|
|
72716
73036
|
const structureSummary = summarizeSourceFileStructure(content, extension, filePath);
|
|
72717
73037
|
if (structureSummary.entityCount > heuristics.maxEntityCountPerFile) {
|
|
72718
73038
|
reasons.push(`entities ${structureSummary.entityCount}/${heuristics.maxEntityCountPerFile}`);
|
|
@@ -72772,6 +73092,7 @@ function countLines(content) {
|
|
|
72772
73092
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72773
73093
|
*/
|
|
72774
73094
|
function summarizeSourceFileStructure(content, extension, filePath) {
|
|
73095
|
+
const ts = getLoadedTypescriptModule();
|
|
72775
73096
|
const scriptKind = getScriptKindForExtension(extension);
|
|
72776
73097
|
const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true, scriptKind);
|
|
72777
73098
|
return {
|
|
@@ -72785,6 +73106,7 @@ function summarizeSourceFileStructure(content, extension, filePath) {
|
|
|
72785
73106
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72786
73107
|
*/
|
|
72787
73108
|
function countEntitiesInSourceFile(sourceFile) {
|
|
73109
|
+
const ts = getLoadedTypescriptModule();
|
|
72788
73110
|
let count = 0;
|
|
72789
73111
|
// Only count top-level declarations to avoid inflating with members or nested scopes.
|
|
72790
73112
|
for (const statement of sourceFile.statements) {
|
|
@@ -72817,6 +73139,7 @@ function countEntitiesInSourceFile(sourceFile) {
|
|
|
72817
73139
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72818
73140
|
*/
|
|
72819
73141
|
function summarizeFunctionsInSourceFile(sourceFile) {
|
|
73142
|
+
const ts = getLoadedTypescriptModule();
|
|
72820
73143
|
let functionCount = 0;
|
|
72821
73144
|
let maxFunctionComplexity = 0;
|
|
72822
73145
|
let mostComplexFunctionName = null;
|
|
@@ -72844,6 +73167,7 @@ function summarizeFunctionsInSourceFile(sourceFile) {
|
|
|
72844
73167
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72845
73168
|
*/
|
|
72846
73169
|
function isCountedFunctionLikeDeclaration(node) {
|
|
73170
|
+
const ts = getLoadedTypescriptModule();
|
|
72847
73171
|
if (ts.isFunctionDeclaration(node) ||
|
|
72848
73172
|
ts.isMethodDeclaration(node) ||
|
|
72849
73173
|
ts.isConstructorDeclaration(node) ||
|
|
@@ -72862,6 +73186,7 @@ function isCountedFunctionLikeDeclaration(node) {
|
|
|
72862
73186
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72863
73187
|
*/
|
|
72864
73188
|
function isNamedFunctionExpression(node) {
|
|
73189
|
+
const ts = getLoadedTypescriptModule();
|
|
72865
73190
|
const parent = node.parent;
|
|
72866
73191
|
return (ts.isVariableDeclaration(parent) || ts.isPropertyDeclaration(parent) || ts.isPropertyAssignment(parent));
|
|
72867
73192
|
}
|
|
@@ -72874,6 +73199,7 @@ function calculateFunctionComplexity(functionNode) {
|
|
|
72874
73199
|
if (!functionNode.body) {
|
|
72875
73200
|
return 1;
|
|
72876
73201
|
}
|
|
73202
|
+
const ts = getLoadedTypescriptModule();
|
|
72877
73203
|
let complexity = 1;
|
|
72878
73204
|
const visitNode = (node) => {
|
|
72879
73205
|
if (node !== functionNode.body && isCountedFunctionLikeDeclaration(node)) {
|
|
@@ -72893,6 +73219,7 @@ function calculateFunctionComplexity(functionNode) {
|
|
|
72893
73219
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72894
73220
|
*/
|
|
72895
73221
|
function isComplexityDecisionNode(node) {
|
|
73222
|
+
const ts = getLoadedTypescriptModule();
|
|
72896
73223
|
if (ts.isIfStatement(node) ||
|
|
72897
73224
|
ts.isConditionalExpression(node) ||
|
|
72898
73225
|
ts.isCatchClause(node) ||
|
|
@@ -72918,6 +73245,7 @@ function isComplexityDecisionNode(node) {
|
|
|
72918
73245
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72919
73246
|
*/
|
|
72920
73247
|
function getFunctionDisplayName(functionNode) {
|
|
73248
|
+
const ts = getLoadedTypescriptModule();
|
|
72921
73249
|
if (ts.isConstructorDeclaration(functionNode)) {
|
|
72922
73250
|
return 'constructor';
|
|
72923
73251
|
}
|
|
@@ -72950,6 +73278,7 @@ function getFunctionDisplayName(functionNode) {
|
|
|
72950
73278
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72951
73279
|
*/
|
|
72952
73280
|
function getBindingNameText(name) {
|
|
73281
|
+
const ts = getLoadedTypescriptModule();
|
|
72953
73282
|
return ts.isIdentifier(name) ? name.text : null;
|
|
72954
73283
|
}
|
|
72955
73284
|
/**
|
|
@@ -72958,6 +73287,7 @@ function getBindingNameText(name) {
|
|
|
72958
73287
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72959
73288
|
*/
|
|
72960
73289
|
function getPropertyNameText(name) {
|
|
73290
|
+
const ts = getLoadedTypescriptModule();
|
|
72961
73291
|
if (ts.isIdentifier(name) || ts.isPrivateIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) {
|
|
72962
73292
|
return name.text;
|
|
72963
73293
|
}
|
|
@@ -72980,6 +73310,7 @@ function buildComplexityReason(structureSummary, maxAllowedFunctionComplexity) {
|
|
|
72980
73310
|
* @private function of analyzeSourceFileForRefactorCandidate
|
|
72981
73311
|
*/
|
|
72982
73312
|
function getScriptKindForExtension(extension) {
|
|
73313
|
+
const ts = getLoadedTypescriptModule();
|
|
72983
73314
|
if (extension === '.tsx') {
|
|
72984
73315
|
return ts.ScriptKind.TSX;
|
|
72985
73316
|
}
|
|
@@ -73589,6 +73920,41 @@ function listPromptsToBeWritten(files, priorityFilter = {}) {
|
|
|
73589
73920
|
isPromptInPriorityFilter(prompt.section, priorityFilter));
|
|
73590
73921
|
}
|
|
73591
73922
|
|
|
73923
|
+
/**
|
|
73924
|
+
* Checks whether a prompt is unrestricted or matches the selected harness/model.
|
|
73925
|
+
*
|
|
73926
|
+
* A prompt status line can contain one or more backtick-delimited model or harness
|
|
73927
|
+
* names. Matching is intentionally based on normalized substrings so a token such as
|
|
73928
|
+
* `gpt` selects any `gpt-*` model and `opus` selects a `claude-opus-*` model.
|
|
73929
|
+
*/
|
|
73930
|
+
function isPromptCompatibleWithRunner(file, section, promptRunnerIdentity) {
|
|
73931
|
+
if (promptRunnerIdentity === undefined) {
|
|
73932
|
+
return true;
|
|
73933
|
+
}
|
|
73934
|
+
const statusLine = section.statusLineIndex === undefined ? undefined : file.lines[section.statusLineIndex];
|
|
73935
|
+
const requiredRunnerTokens = statusLine === undefined ? [] : extractPromptRunnerTokens(statusLine);
|
|
73936
|
+
if (requiredRunnerTokens.length === 0) {
|
|
73937
|
+
return true;
|
|
73938
|
+
}
|
|
73939
|
+
const normalizedRunnerNames = [promptRunnerIdentity.harnessName, promptRunnerIdentity.modelName]
|
|
73940
|
+
.filter((name) => name !== undefined && name.trim() !== '')
|
|
73941
|
+
.map((name) => normalizeToKebabCase(name))
|
|
73942
|
+
.filter((name) => name !== '');
|
|
73943
|
+
return requiredRunnerTokens.some((requiredRunnerToken) => {
|
|
73944
|
+
const normalizedRequiredRunnerToken = normalizeToKebabCase(requiredRunnerToken);
|
|
73945
|
+
return (normalizedRequiredRunnerToken !== '' &&
|
|
73946
|
+
normalizedRunnerNames.some((normalizedRunnerName) => normalizedRunnerName.includes(normalizedRequiredRunnerToken)));
|
|
73947
|
+
});
|
|
73948
|
+
}
|
|
73949
|
+
/**
|
|
73950
|
+
* Extracts model and harness tokens from a prompt status line.
|
|
73951
|
+
*/
|
|
73952
|
+
function extractPromptRunnerTokens(statusLine) {
|
|
73953
|
+
return Array.from(statusLine.matchAll(/`([^`]+)`/gu))
|
|
73954
|
+
.map((match) => { var _a, _b; return (_b = (_a = match[1]) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : ''; })
|
|
73955
|
+
.filter((token) => token !== '');
|
|
73956
|
+
}
|
|
73957
|
+
|
|
73592
73958
|
/**
|
|
73593
73959
|
* Parses a prompt markdown file into sections and metadata.
|
|
73594
73960
|
*/
|
|
@@ -73636,11 +74002,11 @@ function parsePromptFile(filePath, content) {
|
|
|
73636
74002
|
};
|
|
73637
74003
|
}
|
|
73638
74004
|
/**
|
|
73639
|
-
* Parses a status line like "[ ] !!"
|
|
74005
|
+
* Parses a status line like "[ ] !!", "[ ] use `gpt` !!!!!" or "[-]" into status and priority.
|
|
73640
74006
|
* For [x] done and [!] failed prompts, allow metadata after the status marker.
|
|
73641
74007
|
*/
|
|
73642
74008
|
function parseStatusLine(line) {
|
|
73643
|
-
var _a, _b, _c, _d
|
|
74009
|
+
var _a, _b, _c, _d;
|
|
73644
74010
|
// For done prompts [x], allow any content after (for cost/time metadata)
|
|
73645
74011
|
const doneMatch = line.match(/^\[(?<status>[xX])\]/);
|
|
73646
74012
|
if (doneMatch) {
|
|
@@ -73651,21 +74017,23 @@ function parseStatusLine(line) {
|
|
|
73651
74017
|
if (failedMatch) {
|
|
73652
74018
|
return { status: 'failed', priority: 0 };
|
|
73653
74019
|
}
|
|
73654
|
-
// For
|
|
73655
|
-
|
|
73656
|
-
|
|
73657
|
-
return undefined;
|
|
74020
|
+
// For not-ready [-], keep the historical clean-line syntax.
|
|
74021
|
+
if (/^\[-\]\s*!*\s*$/u.test(line)) {
|
|
74022
|
+
return { status: 'not-ready', priority: 0 };
|
|
73658
74023
|
}
|
|
73659
|
-
|
|
73660
|
-
|
|
73661
|
-
|
|
73662
|
-
|
|
74024
|
+
// Todo [ ] may contain backtick-delimited model/harness tokens and priority markers
|
|
74025
|
+
// before or after those tokens. Other trailing text remains an invalid status line.
|
|
74026
|
+
const todoMatch = line.match(/^\[ \](?<details>.*)$/u);
|
|
74027
|
+
if (!todoMatch) {
|
|
74028
|
+
return undefined;
|
|
73663
74029
|
}
|
|
73664
|
-
|
|
73665
|
-
|
|
74030
|
+
const details = (_b = (_a = todoMatch.groups) === null || _a === void 0 ? void 0 : _a.details) !== null && _b !== void 0 ? _b : '';
|
|
74031
|
+
const isPriorityOnly = /^[!\s]*$/u.test(details);
|
|
74032
|
+
const hasPromptRunnerTokens = extractPromptRunnerTokens(line).length > 0;
|
|
74033
|
+
if (details.trim() !== '' && !isPriorityOnly && !hasPromptRunnerTokens) {
|
|
74034
|
+
return undefined;
|
|
73666
74035
|
}
|
|
73667
|
-
|
|
73668
|
-
return { status, priority };
|
|
74036
|
+
return { status: 'todo', priority: (_d = (_c = details.match(/!/gu)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0 };
|
|
73669
74037
|
}
|
|
73670
74038
|
/**
|
|
73671
74039
|
* Finds the first non-empty line index between two bounds.
|
|
@@ -73801,6 +74169,243 @@ var findUnwrittenPrompts$1 = /*#__PURE__*/Object.freeze({
|
|
|
73801
74169
|
findUnwrittenPrompts: findUnwrittenPrompts
|
|
73802
74170
|
});
|
|
73803
74171
|
|
|
74172
|
+
/**
|
|
74173
|
+
* Builds a normalized temporary shell script path for prompt runners.
|
|
74174
|
+
*/
|
|
74175
|
+
function buildTemporaryPromptScriptPath(options) {
|
|
74176
|
+
const sourceFileName = basename(options.sourceFileName);
|
|
74177
|
+
const scriptFileName = `${sourceFileName.replace(/\.[^.]+$/u, '')}${options.suffix || ''}.sh`;
|
|
74178
|
+
return resolvePromptbookTemporaryPath(options.projectPath, options.scriptDirectoryName, scriptFileName);
|
|
74179
|
+
}
|
|
74180
|
+
|
|
74181
|
+
/**
|
|
74182
|
+
* Marker the pinged harness is asked to prefix its answer with, so the reply can be recognized
|
|
74183
|
+
* in the raw runner output of every supported harness.
|
|
74184
|
+
*
|
|
74185
|
+
* Note: The marker must stay free of regular-expression metacharacters, because
|
|
74186
|
+
* `extractCoderPingAnswer` builds its pattern from it.
|
|
74187
|
+
*/
|
|
74188
|
+
const CODER_PING_ANSWER_MARKER = 'PTBK-CODER-PING-ANSWER';
|
|
74189
|
+
/**
|
|
74190
|
+
* First factor of the dummy multiplication the pinged harness is asked to compute.
|
|
74191
|
+
*/
|
|
74192
|
+
const CODER_PING_FIRST_FACTOR = 6;
|
|
74193
|
+
/**
|
|
74194
|
+
* Second factor of the dummy multiplication the pinged harness is asked to compute.
|
|
74195
|
+
*/
|
|
74196
|
+
const CODER_PING_SECOND_FACTOR = 7;
|
|
74197
|
+
/**
|
|
74198
|
+
* Answer a working harness and model returns for the dummy work of `ptbk coder ping`.
|
|
74199
|
+
*/
|
|
74200
|
+
const CODER_PING_EXPECTED_ANSWER = String(CODER_PING_FIRST_FACTOR * CODER_PING_SECOND_FACTOR);
|
|
74201
|
+
/**
|
|
74202
|
+
* Builds the dummy prompt sent by `ptbk coder ping`.
|
|
74203
|
+
*
|
|
74204
|
+
* The work is intentionally the smallest possible one that still reaches the model: it spends a
|
|
74205
|
+
* negligible amount of the harness quota, it needs no tool and it explicitly forbids touching the
|
|
74206
|
+
* project, so a ping leaves the project exactly as it was.
|
|
74207
|
+
*/
|
|
74208
|
+
function buildCoderPingPrompt() {
|
|
74209
|
+
return spaceTrim(`
|
|
74210
|
+
# Promptbook connection check
|
|
74211
|
+
|
|
74212
|
+
This is an automated \`ptbk coder ping\` connection check, not a coding task.
|
|
74213
|
+
|
|
74214
|
+
Do exactly this and nothing else:
|
|
74215
|
+
|
|
74216
|
+
1. Multiply \`${CODER_PING_FIRST_FACTOR}\` by \`${CODER_PING_SECOND_FACTOR}\`.
|
|
74217
|
+
2. Answer with one single line \`${CODER_PING_ANSWER_MARKER}: <result>\` where \`<result>\` is the number you computed.
|
|
74218
|
+
|
|
74219
|
+
Rules:
|
|
74220
|
+
|
|
74221
|
+
- Do not read, create, change, move or delete any file.
|
|
74222
|
+
- Do not run any command and do not use any tool.
|
|
74223
|
+
- Do not write anything except the single answer line.
|
|
74224
|
+
`);
|
|
74225
|
+
}
|
|
74226
|
+
|
|
74227
|
+
/**
|
|
74228
|
+
* Pattern matching one answer line produced by the pinged harness.
|
|
74229
|
+
*
|
|
74230
|
+
* The captured answer deliberately stops at a quote, a backslash or a line break, so an answer
|
|
74231
|
+
* embedded in a JSON event stream — as produced by Claude Code, Opencode or Codex `--json` — is
|
|
74232
|
+
* captured without the surrounding JSON.
|
|
74233
|
+
*/
|
|
74234
|
+
const CODER_PING_ANSWER_PATTERN = new RegExp(`${CODER_PING_ANSWER_MARKER}\\s*:[ \\t]*([^\\r\\n"\\\\]*)`, 'gu');
|
|
74235
|
+
/**
|
|
74236
|
+
* Extracts the answer of a pinged harness from the runtime log of its runner shell.
|
|
74237
|
+
*
|
|
74238
|
+
* Only the raw output of the last execution is searched, so the answer marker contained in the
|
|
74239
|
+
* prompt of the raw input is never mistaken for the answer of the harness.
|
|
74240
|
+
*
|
|
74241
|
+
* @returns The answer of the harness, or `null` when the harness produced no recognizable answer
|
|
74242
|
+
*/
|
|
74243
|
+
function extractCoderPingAnswer(runtimeLog) {
|
|
74244
|
+
var _a;
|
|
74245
|
+
const rawOutput = runtimeLog.split(SCRIPT_EXECUTION_LOG_RAW_OUTPUT_MARKER).pop();
|
|
74246
|
+
if (rawOutput === undefined) {
|
|
74247
|
+
return null;
|
|
74248
|
+
}
|
|
74249
|
+
// Note: The last answer wins because harnesses which stream partial messages repeat the growing answer line
|
|
74250
|
+
const answers = Array.from(rawOutput.matchAll(CODER_PING_ANSWER_PATTERN))
|
|
74251
|
+
.map((match) => (match[1] || '').trim())
|
|
74252
|
+
.filter((answer) => answer !== '');
|
|
74253
|
+
return (_a = answers[answers.length - 1]) !== null && _a !== void 0 ? _a : null;
|
|
74254
|
+
}
|
|
74255
|
+
|
|
74256
|
+
/**
|
|
74257
|
+
* Temporary subdirectory used for the `ptbk coder ping` runner shell script and its runtime log.
|
|
74258
|
+
*/
|
|
74259
|
+
const CODER_PING_SCRIPT_DIRECTORY_NAME = 'coder-ping';
|
|
74260
|
+
/**
|
|
74261
|
+
* Base name of the temporary `ptbk coder ping` runner shell script.
|
|
74262
|
+
*/
|
|
74263
|
+
const CODER_PING_SCRIPT_SOURCE_NAME = 'ping';
|
|
74264
|
+
/**
|
|
74265
|
+
* Sends one tiny dummy prompt through the selected harness and model and measures the round trip.
|
|
74266
|
+
*
|
|
74267
|
+
* The ping reuses the very same runner the coding queue uses, so it really exercises the configured
|
|
74268
|
+
* harness, model, thinking level and authentication — including the retry behavior on rate limits.
|
|
74269
|
+
* Both temporary artifacts it creates are removed again, so the project is left as it was.
|
|
74270
|
+
*/
|
|
74271
|
+
async function pingCoderHarness(options) {
|
|
74272
|
+
const projectPath = options.projectPath || process.cwd();
|
|
74273
|
+
const { runner, runnerMetadata } = resolvePromptRunner(options);
|
|
74274
|
+
const scriptPath = buildTemporaryPromptScriptPath({
|
|
74275
|
+
projectPath,
|
|
74276
|
+
scriptDirectoryName: CODER_PING_SCRIPT_DIRECTORY_NAME,
|
|
74277
|
+
sourceFileName: CODER_PING_SCRIPT_SOURCE_NAME,
|
|
74278
|
+
});
|
|
74279
|
+
const startedTimeMs = Date.now();
|
|
74280
|
+
const { answer, usage, loginMethod } = await withPromptRuntimeLog(scriptPath, async (logPath) => {
|
|
74281
|
+
var _a;
|
|
74282
|
+
const result = await runner.runPrompt({
|
|
74283
|
+
prompt: buildCoderPingPrompt(),
|
|
74284
|
+
scriptPath,
|
|
74285
|
+
projectPath,
|
|
74286
|
+
logPath,
|
|
74287
|
+
shouldPrintLiveOutput: (_a = options.shouldPrintLiveOutput) !== null && _a !== void 0 ? _a : false,
|
|
74288
|
+
preserveArtifactsOnSuccess: false,
|
|
74289
|
+
});
|
|
74290
|
+
return { ...result, answer: extractCoderPingAnswer(await readRuntimeLog(logPath)) };
|
|
74291
|
+
}, { preserveArtifactsOnSuccess: false });
|
|
74292
|
+
return {
|
|
74293
|
+
runnerName: runnerMetadata.runnerName,
|
|
74294
|
+
modelName: runnerMetadata.modelName,
|
|
74295
|
+
thinkingLevel: options.thinkingLevel,
|
|
74296
|
+
answer,
|
|
74297
|
+
isAnswerCorrect: answer === CODER_PING_EXPECTED_ANSWER,
|
|
74298
|
+
durationMs: Date.now() - startedTimeMs,
|
|
74299
|
+
usage,
|
|
74300
|
+
loginMethod,
|
|
74301
|
+
};
|
|
74302
|
+
}
|
|
74303
|
+
/**
|
|
74304
|
+
* Reads the runtime log of the finished ping, treating an unreadable log as no output at all.
|
|
74305
|
+
*/
|
|
74306
|
+
async function readRuntimeLog(logPath) {
|
|
74307
|
+
return await readFile(logPath, 'utf-8').catch(() => '');
|
|
74308
|
+
}
|
|
74309
|
+
|
|
74310
|
+
var pingCoderHarness$1 = /*#__PURE__*/Object.freeze({
|
|
74311
|
+
__proto__: null,
|
|
74312
|
+
pingCoderHarness: pingCoderHarness
|
|
74313
|
+
});
|
|
74314
|
+
|
|
74315
|
+
/**
|
|
74316
|
+
* Formats usage price for display in prompt status lines and task details.
|
|
74317
|
+
* Examples:
|
|
74318
|
+
* - "$0.12" (certain)
|
|
74319
|
+
* - "~$3.05" (uncertain)
|
|
74320
|
+
* - "$0.00" (zero cost)
|
|
74321
|
+
* - "<$0.01" (tiny non-zero cost)
|
|
74322
|
+
*
|
|
74323
|
+
* @private internal utility of the prompt runners and the Agents Server task details
|
|
74324
|
+
*/
|
|
74325
|
+
function formatUsagePrice(usage) {
|
|
74326
|
+
const price = usage.price.value;
|
|
74327
|
+
const isUncertain = usage.price.isUncertain === true;
|
|
74328
|
+
const prefix = isUncertain ? '~' : '';
|
|
74329
|
+
if (price === 0) {
|
|
74330
|
+
return `${prefix}$0.00`;
|
|
74331
|
+
}
|
|
74332
|
+
if (price < 0.01) {
|
|
74333
|
+
return `${prefix}<$0.01`;
|
|
74334
|
+
}
|
|
74335
|
+
if (price < 1) {
|
|
74336
|
+
return `${prefix}$${price.toFixed(4)}`;
|
|
74337
|
+
}
|
|
74338
|
+
return `${prefix}$${price.toFixed(2)}`;
|
|
74339
|
+
}
|
|
74340
|
+
|
|
74341
|
+
/**
|
|
74342
|
+
* Formats runner details for prompt status lines.
|
|
74343
|
+
*/
|
|
74344
|
+
function formatRunnerSignature(runnerName, modelName, thinkingLevel) {
|
|
74345
|
+
const normalizedRunner = runnerName === null || runnerName === void 0 ? void 0 : runnerName.trim();
|
|
74346
|
+
const normalizedModel = modelName === null || modelName === void 0 ? void 0 : modelName.trim();
|
|
74347
|
+
const thinkingLevelSuffix = thinkingLevel ? ` thinking \`${thinkingLevel}\`` : '';
|
|
74348
|
+
if (!normalizedRunner && !normalizedModel) {
|
|
74349
|
+
return 'unknown';
|
|
74350
|
+
}
|
|
74351
|
+
const runnerLabel = normalizedRunner || 'unknown';
|
|
74352
|
+
if (!normalizedModel) {
|
|
74353
|
+
return `${runnerLabel}${thinkingLevelSuffix}`;
|
|
74354
|
+
}
|
|
74355
|
+
return `${runnerLabel} \`${normalizedModel}\`${thinkingLevelSuffix}`;
|
|
74356
|
+
}
|
|
74357
|
+
|
|
74358
|
+
/**
|
|
74359
|
+
* Prints the compact summary of one finished `ptbk coder ping`.
|
|
74360
|
+
*/
|
|
74361
|
+
function printCoderPingResult(result) {
|
|
74362
|
+
const runnerSignature = formatRunnerSignature(result.runnerName, result.modelName, result.thinkingLevel);
|
|
74363
|
+
const loginMethodLabel = formatCodexLoginMethod(result.loginMethod);
|
|
74364
|
+
const loginMethodSuffix = loginMethodLabel === undefined ? '' : ` (${loginMethodLabel})`;
|
|
74365
|
+
console.info(colors.green(`🏓 ${runnerSignature}${loginMethodSuffix} answered in ${formatCoderPingResponseTime(result.durationMs)}`));
|
|
74366
|
+
console.info(colors.gray(` Answer: ${formatCoderPingAnswer(result)}`));
|
|
74367
|
+
console.info(colors.gray(` Usage: ${formatCoderPingUsage(result.usage)}`));
|
|
74368
|
+
}
|
|
74369
|
+
/**
|
|
74370
|
+
* Formats the measured round-trip time, keeping the sub-second precision a response time needs.
|
|
74371
|
+
*/
|
|
74372
|
+
function formatCoderPingResponseTime(durationMs) {
|
|
74373
|
+
return `${(durationMs / 1000).toFixed(2)}s`;
|
|
74374
|
+
}
|
|
74375
|
+
/**
|
|
74376
|
+
* Formats the answer of the pinged harness together with what was expected from it.
|
|
74377
|
+
*/
|
|
74378
|
+
function formatCoderPingAnswer(result) {
|
|
74379
|
+
if (result.answer === null) {
|
|
74380
|
+
return `Reached, but the answer line was missing from the output (expected \`${CODER_PING_EXPECTED_ANSWER}\`)`;
|
|
74381
|
+
}
|
|
74382
|
+
if (result.isAnswerCorrect) {
|
|
74383
|
+
return result.answer;
|
|
74384
|
+
}
|
|
74385
|
+
return `${result.answer} (expected \`${CODER_PING_EXPECTED_ANSWER}\`)`;
|
|
74386
|
+
}
|
|
74387
|
+
/**
|
|
74388
|
+
* Formats the resources the pinged harness reported for the dummy work.
|
|
74389
|
+
*/
|
|
74390
|
+
function formatCoderPingUsage(usage) {
|
|
74391
|
+
return [
|
|
74392
|
+
formatUsagePrice(usage),
|
|
74393
|
+
`${formatUncertainCount(usage.input.tokensCount)} input tokens`,
|
|
74394
|
+
`${formatUncertainCount(usage.output.tokensCount)} output tokens`,
|
|
74395
|
+
].join(', ');
|
|
74396
|
+
}
|
|
74397
|
+
/**
|
|
74398
|
+
* Formats one counted usage value, marking an estimated count with a leading `~`.
|
|
74399
|
+
*/
|
|
74400
|
+
function formatUncertainCount(count) {
|
|
74401
|
+
return `${count.isUncertain === true ? '~' : ''}${Math.round(count.value)}`;
|
|
74402
|
+
}
|
|
74403
|
+
|
|
74404
|
+
var printCoderPingResult$1 = /*#__PURE__*/Object.freeze({
|
|
74405
|
+
__proto__: null,
|
|
74406
|
+
printCoderPingResult: printCoderPingResult
|
|
74407
|
+
});
|
|
74408
|
+
|
|
73804
74409
|
/**
|
|
73805
74410
|
* Default wait duration applied before retrying a failed prompt round.
|
|
73806
74411
|
*/
|
|
@@ -73808,7 +74413,7 @@ const DEFAULT_WAIT_AFTER_ERROR_MS = 10 * 60 * 1000;
|
|
|
73808
74413
|
/**
|
|
73809
74414
|
* CLI usage text for this script.
|
|
73810
74415
|
*/
|
|
73811
|
-
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--harness <harness-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--preserve-logs] [--isolate] [--no-ui] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--min-priority <minimum-priority>] [--max-priority <maximum-priority>] [--limit <run-count>] [--allow-credits] [--auto-migrate] [--allow-destructive-auto-migrate] [--wait-after-prompt <duration>] [--wait-between-prompts <duration>] [--wait-after-error <duration>] [--no-auto] [--no-commit] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push] [--auto-pull]';
|
|
74416
|
+
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--harness <harness-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--test-before <no|yes-and-fail|yes-and-fix>] [--preserve-logs] [--isolate] [--no-ui] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--min-priority <minimum-priority>] [--max-priority <maximum-priority>] [--limit <run-count>] [--allow-credits] [--auto-migrate] [--allow-destructive-auto-migrate] [--wait-after-prompt <duration>] [--wait-between-prompts <duration>] [--wait-after-error <duration>] [--no-auto] [--no-commit] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push] [--auto-pull]';
|
|
73812
74417
|
/**
|
|
73813
74418
|
* Top-level flags supported by this command.
|
|
73814
74419
|
*/
|
|
@@ -73818,6 +74423,7 @@ const KNOWN_OPTION_FLAGS = new Set([
|
|
|
73818
74423
|
'--model',
|
|
73819
74424
|
'--context',
|
|
73820
74425
|
'--test',
|
|
74426
|
+
'--test-before',
|
|
73821
74427
|
'--preserve-logs',
|
|
73822
74428
|
'--isolate',
|
|
73823
74429
|
'--no-ui',
|
|
@@ -73856,6 +74462,8 @@ function parseRunOptions(args) {
|
|
|
73856
74462
|
const context = readOptionValue(args, '--context');
|
|
73857
74463
|
const hasTestCommandFlag = args.includes('--test');
|
|
73858
74464
|
const testCommand = readVariadicOptionValue(args, '--test');
|
|
74465
|
+
const hasTestBeforeFlag = args.includes('--test-before');
|
|
74466
|
+
const testBefore = parseTestBeforeOption(readOptionValue(args, '--test-before'), hasTestBeforeFlag);
|
|
73859
74467
|
const preserveLogs = args.includes('--preserve-logs');
|
|
73860
74468
|
const isIsolated = args.includes('--isolate');
|
|
73861
74469
|
const noUi = args.includes('--no-ui');
|
|
@@ -73928,6 +74536,7 @@ function parseRunOptions(args) {
|
|
|
73928
74536
|
model,
|
|
73929
74537
|
context,
|
|
73930
74538
|
testCommand,
|
|
74539
|
+
testBefore,
|
|
73931
74540
|
thinkingLevel,
|
|
73932
74541
|
priority: minimumPriority !== null && minimumPriority !== void 0 ? minimumPriority : 0,
|
|
73933
74542
|
minimumPriority,
|
|
@@ -73936,6 +74545,21 @@ function parseRunOptions(args) {
|
|
|
73936
74545
|
limit,
|
|
73937
74546
|
};
|
|
73938
74547
|
}
|
|
74548
|
+
/**
|
|
74549
|
+
* Parses and validates the optional pre-coding verification mode.
|
|
74550
|
+
*/
|
|
74551
|
+
function parseTestBeforeOption(value, hasTestBeforeFlag) {
|
|
74552
|
+
if (value === undefined) {
|
|
74553
|
+
if (hasTestBeforeFlag) {
|
|
74554
|
+
exitWithUsageError(`Missing value for --test-before. Use one of: ${TEST_BEFORE_MODE_VALUES.join(', ')}.`);
|
|
74555
|
+
}
|
|
74556
|
+
return 'no';
|
|
74557
|
+
}
|
|
74558
|
+
if (!isTestBeforeMode(value)) {
|
|
74559
|
+
exitWithUsageError(`Invalid value for --test-before: "${value}". Use one of: ${TEST_BEFORE_MODE_VALUES.join(', ')}.`);
|
|
74560
|
+
}
|
|
74561
|
+
return value;
|
|
74562
|
+
}
|
|
73939
74563
|
/**
|
|
73940
74564
|
* Reads a duration-typed CLI flag, applying the provided default when the flag is absent.
|
|
73941
74565
|
*/
|
|
@@ -75694,6 +76318,14 @@ function splitSqlStatements(sql) {
|
|
|
75694
76318
|
.filter((statement) => statement !== '');
|
|
75695
76319
|
}
|
|
75696
76320
|
|
|
76321
|
+
/**
|
|
76322
|
+
* Loads the PostgreSQL client (`pg`) on demand
|
|
76323
|
+
*
|
|
76324
|
+
* Note: [🐌] Loaded lazily to keep the startup of the `ptbk` CLI utility fast
|
|
76325
|
+
*
|
|
76326
|
+
* @private function of runAutoMigrateTestingServers
|
|
76327
|
+
*/
|
|
76328
|
+
const loadPostgresModule = createLazyModuleLoader(() => import('pg'));
|
|
75697
76329
|
/**
|
|
75698
76330
|
* Migration targets for testing servers that should be migrated by coding-script auto-migration.
|
|
75699
76331
|
*/
|
|
@@ -75771,6 +76403,7 @@ async function runAutoMigrateTestingServersImmediately(options) {
|
|
|
75771
76403
|
* @returns Pending migration files grouped by prefix.
|
|
75772
76404
|
*/
|
|
75773
76405
|
async function listPendingMigrationsByPrefix(options) {
|
|
76406
|
+
const { Client } = await loadPostgresModule();
|
|
75774
76407
|
const client = new Client({
|
|
75775
76408
|
connectionString: options.connectionString,
|
|
75776
76409
|
ssl: { rejectUnauthorized: false },
|
|
@@ -75928,15 +76561,6 @@ function buildCommitMessage(file, section) {
|
|
|
75928
76561
|
return lines.join(file.eol);
|
|
75929
76562
|
}
|
|
75930
76563
|
|
|
75931
|
-
/**
|
|
75932
|
-
* Builds a normalized temporary shell script path for prompt runners.
|
|
75933
|
-
*/
|
|
75934
|
-
function buildTemporaryPromptScriptPath(options) {
|
|
75935
|
-
const sourceFileName = basename(options.sourceFileName);
|
|
75936
|
-
const scriptFileName = `${sourceFileName.replace(/\.[^.]+$/u, '')}${options.suffix || ''}.sh`;
|
|
75937
|
-
return resolvePromptbookTemporaryPath(options.projectPath, options.scriptDirectoryName, scriptFileName);
|
|
75938
|
-
}
|
|
75939
|
-
|
|
75940
76564
|
/**
|
|
75941
76565
|
* Builds the suffix which disambiguates one prompt section inside its prompt file.
|
|
75942
76566
|
*
|
|
@@ -75963,32 +76587,6 @@ function buildScriptPath(file, section, projectPath = process.cwd()) {
|
|
|
75963
76587
|
});
|
|
75964
76588
|
}
|
|
75965
76589
|
|
|
75966
|
-
/**
|
|
75967
|
-
* Formats usage price for display in prompt status lines and task details.
|
|
75968
|
-
* Examples:
|
|
75969
|
-
* - "$0.12" (certain)
|
|
75970
|
-
* - "~$3.05" (uncertain)
|
|
75971
|
-
* - "$0.00" (zero cost)
|
|
75972
|
-
* - "<$0.01" (tiny non-zero cost)
|
|
75973
|
-
*
|
|
75974
|
-
* @private internal utility of the prompt runners and the Agents Server task details
|
|
75975
|
-
*/
|
|
75976
|
-
function formatUsagePrice(usage) {
|
|
75977
|
-
const price = usage.price.value;
|
|
75978
|
-
const isUncertain = usage.price.isUncertain === true;
|
|
75979
|
-
const prefix = isUncertain ? '~' : '';
|
|
75980
|
-
if (price === 0) {
|
|
75981
|
-
return `${prefix}$0.00`;
|
|
75982
|
-
}
|
|
75983
|
-
if (price < 0.01) {
|
|
75984
|
-
return `${prefix}<$0.01`;
|
|
75985
|
-
}
|
|
75986
|
-
if (price < 1) {
|
|
75987
|
-
return `${prefix}$${price.toFixed(4)}`;
|
|
75988
|
-
}
|
|
75989
|
-
return `${prefix}$${price.toFixed(2)}`;
|
|
75990
|
-
}
|
|
75991
|
-
|
|
75992
76590
|
/**
|
|
75993
76591
|
* Human-readable labels for each coder run step kind shown in prompt status lines.
|
|
75994
76592
|
*/
|
|
@@ -76034,20 +76632,13 @@ function formatPromptAttemptMetadata(status, attemptCount) {
|
|
|
76034
76632
|
}
|
|
76035
76633
|
|
|
76036
76634
|
/**
|
|
76037
|
-
*
|
|
76635
|
+
* Replaces the complete todo status line while preserving its indentation.
|
|
76636
|
+
*
|
|
76637
|
+
* The complete line is replaced because a todo status can contain a required
|
|
76638
|
+
* model/harness token in addition to priority markers.
|
|
76038
76639
|
*/
|
|
76039
|
-
function
|
|
76040
|
-
|
|
76041
|
-
const normalizedModel = modelName === null || modelName === void 0 ? void 0 : modelName.trim();
|
|
76042
|
-
const thinkingLevelSuffix = thinkingLevel ? ` thinking \`${thinkingLevel}\`` : '';
|
|
76043
|
-
if (!normalizedRunner && !normalizedModel) {
|
|
76044
|
-
return 'unknown';
|
|
76045
|
-
}
|
|
76046
|
-
const runnerLabel = normalizedRunner || 'unknown';
|
|
76047
|
-
if (!normalizedModel) {
|
|
76048
|
-
return `${runnerLabel}${thinkingLevelSuffix}`;
|
|
76049
|
-
}
|
|
76050
|
-
return `${runnerLabel} \`${normalizedModel}\`${thinkingLevelSuffix}`;
|
|
76640
|
+
function replacePromptTodoStatusLine(line, replacementStatusLine) {
|
|
76641
|
+
return line.replace(/^(?<indentation>\s*)\[\s*\].*$/u, `$<indentation>${replacementStatusLine}`);
|
|
76051
76642
|
}
|
|
76052
76643
|
|
|
76053
76644
|
/**
|
|
@@ -76067,8 +76658,8 @@ function markPromptDone(file, section, steps, runnerName, modelName, attemptCoun
|
|
|
76067
76658
|
const loginMethodSuffix = loginMethodLabel ? ` (${loginMethodLabel})` : '';
|
|
76068
76659
|
const stepsSummary = formatCoderRunSteps(steps);
|
|
76069
76660
|
const stepsSuffix = stepsSummary === '' ? '' : ` - ${stepsSummary}`;
|
|
76070
|
-
// Replace
|
|
76071
|
-
file.lines[section.statusLineIndex] = line
|
|
76661
|
+
// Replace the complete todo status, including any required model/harness token.
|
|
76662
|
+
file.lines[section.statusLineIndex] = replacePromptTodoStatusLine(line, `[x] ${attemptMetadata}by ${runnerSignature}${loginMethodSuffix}${stepsSuffix}`);
|
|
76072
76663
|
}
|
|
76073
76664
|
|
|
76074
76665
|
/**
|
|
@@ -76086,8 +76677,10 @@ function markPromptFailed(file, section, runnerName, modelName, promptExecutionS
|
|
|
76086
76677
|
const attemptMetadata = formatPromptAttemptMetadata('failed', attemptCount);
|
|
76087
76678
|
const duration = moment().diff(promptExecutionStartedDate);
|
|
76088
76679
|
const durationString = moment.duration(duration).humanize();
|
|
76089
|
-
const failureDetails = attemptMetadata === ''
|
|
76090
|
-
|
|
76680
|
+
const failureDetails = attemptMetadata === ''
|
|
76681
|
+
? `failed after ${durationString} by ${runnerSignature}`
|
|
76682
|
+
: `${attemptMetadata}${durationString} by ${runnerSignature}`;
|
|
76683
|
+
file.lines[section.statusLineIndex] = replacePromptTodoStatusLine(line, `[!] ${failureDetails}`);
|
|
76091
76684
|
}
|
|
76092
76685
|
|
|
76093
76686
|
/**
|
|
@@ -77057,17 +77650,18 @@ function toProjectRelativeGitPath(projectPath, path) {
|
|
|
77057
77650
|
/**
|
|
77058
77651
|
* Lists todo prompts that are ready to run (no authoring placeholders).
|
|
77059
77652
|
*/
|
|
77060
|
-
function listRunnablePrompts(files, priorityFilter = {}) {
|
|
77653
|
+
function listRunnablePrompts(files, priorityFilter = {}, promptRunnerIdentity) {
|
|
77061
77654
|
return listTodoPrompts(files).filter((prompt) => !isPromptToBeWritten(prompt.file, prompt.section) &&
|
|
77062
|
-
isPromptInPriorityFilter(prompt.section, priorityFilter)
|
|
77655
|
+
isPromptInPriorityFilter(prompt.section, priorityFilter) &&
|
|
77656
|
+
isPromptCompatibleWithRunner(prompt.file, prompt.section, promptRunnerIdentity));
|
|
77063
77657
|
}
|
|
77064
77658
|
|
|
77065
77659
|
/**
|
|
77066
77660
|
* Selects the next runnable prompt based on priority.
|
|
77067
77661
|
*/
|
|
77068
|
-
function findNextTodoPrompt(files, priorityFilter = {}) {
|
|
77662
|
+
function findNextTodoPrompt(files, priorityFilter = {}, promptRunnerIdentity) {
|
|
77069
77663
|
let nextPrompt;
|
|
77070
|
-
for (const prompt of listRunnablePrompts(files, priorityFilter)) {
|
|
77664
|
+
for (const prompt of listRunnablePrompts(files, priorityFilter, promptRunnerIdentity)) {
|
|
77071
77665
|
if (!nextPrompt || prompt.section.priority > nextPrompt.section.priority) {
|
|
77072
77666
|
nextPrompt = prompt;
|
|
77073
77667
|
}
|
|
@@ -77078,8 +77672,8 @@ function findNextTodoPrompt(files, priorityFilter = {}) {
|
|
|
77078
77672
|
/**
|
|
77079
77673
|
* Lists upcoming tasks that are ready to run (no authoring placeholders).
|
|
77080
77674
|
*/
|
|
77081
|
-
function listUpcomingTasks(files, priorityFilter = {}) {
|
|
77082
|
-
return listRunnablePrompts(files, priorityFilter).map(({ file, section }) => ({
|
|
77675
|
+
function listUpcomingTasks(files, priorityFilter = {}, promptRunnerIdentity) {
|
|
77676
|
+
return listRunnablePrompts(files, priorityFilter, promptRunnerIdentity).map(({ file, section }) => ({
|
|
77083
77677
|
label: buildPromptLabelForDisplay(file, section),
|
|
77084
77678
|
summary: buildPromptSummary(file, section),
|
|
77085
77679
|
priority: section.priority,
|
|
@@ -77223,6 +77817,71 @@ async function buildCoderRunAgentVisual(agentSource) {
|
|
|
77223
77817
|
}
|
|
77224
77818
|
}
|
|
77225
77819
|
|
|
77820
|
+
/**
|
|
77821
|
+
* Creates the one queue prompt used to repair a pre-existing test failure.
|
|
77822
|
+
*/
|
|
77823
|
+
async function createTestBeforeRepairPrompt(options) {
|
|
77824
|
+
const description = spaceTrim((block) => `
|
|
77825
|
+
Fix the existing test failures before implementing any queued coding tasks.
|
|
77826
|
+
|
|
77827
|
+
The verification command \`${options.testCommand}\` failed before coding started. Fix the underlying failure without weakening or removing the tests, and leave the project ready for the remaining coding prompts.
|
|
77828
|
+
|
|
77829
|
+
## Verification output
|
|
77830
|
+
|
|
77831
|
+
\`\`\`
|
|
77832
|
+
${block(limitTestOutput(options.testOutput))}
|
|
77833
|
+
\`\`\`
|
|
77834
|
+
`);
|
|
77835
|
+
const createdPrompt = await addCoderPrompt({
|
|
77836
|
+
projectPath: options.projectPath,
|
|
77837
|
+
description,
|
|
77838
|
+
priority: 0,
|
|
77839
|
+
});
|
|
77840
|
+
const promptPath = join(options.projectPath, createdPrompt.filePath);
|
|
77841
|
+
const promptFile = parsePromptFile(promptPath, await readFile(promptPath, 'utf-8'));
|
|
77842
|
+
const section = promptFile.sections[0];
|
|
77843
|
+
if (!section) {
|
|
77844
|
+
throw new UnexpectedError(spaceTrim(`
|
|
77845
|
+
The pre-coding test repair prompt was created at \`${createdPrompt.filePath}\` without a runnable section.
|
|
77846
|
+
`));
|
|
77847
|
+
}
|
|
77848
|
+
return { file: promptFile, section };
|
|
77849
|
+
}
|
|
77850
|
+
|
|
77851
|
+
/**
|
|
77852
|
+
* Runs the configured verification command before the first coding prompt.
|
|
77853
|
+
*/
|
|
77854
|
+
async function runTestBefore(options) {
|
|
77855
|
+
var _a, _b;
|
|
77856
|
+
const runPromptTestCommandExecutor = (_a = options.runPromptTestCommandExecutor) !== null && _a !== void 0 ? _a : runPromptTestCommand;
|
|
77857
|
+
const initialTestStatusMessage = `Running initial tests before the agent coding starts: ${options.testCommand}`;
|
|
77858
|
+
await ((_b = options.waitForPauseCheckpoint) === null || _b === void 0 ? void 0 : _b.call(options, {
|
|
77859
|
+
checkpointLabel: 'running initial tests before the agent coding starts',
|
|
77860
|
+
phase: 'verifying',
|
|
77861
|
+
statusMessage: initialTestStatusMessage,
|
|
77862
|
+
}));
|
|
77863
|
+
console.info(colors.gray(initialTestStatusMessage));
|
|
77864
|
+
try {
|
|
77865
|
+
const testOutput = await runPromptTestCommandExecutor({
|
|
77866
|
+
command: options.testCommand,
|
|
77867
|
+
projectPath: options.projectPath,
|
|
77868
|
+
scriptPath: buildTemporaryPromptScriptPath({
|
|
77869
|
+
projectPath: options.projectPath,
|
|
77870
|
+
scriptDirectoryName: 'coder-prompts',
|
|
77871
|
+
sourceFileName: 'test-before',
|
|
77872
|
+
}),
|
|
77873
|
+
});
|
|
77874
|
+
console.info(colors.green('Pre-coding tests passed.'));
|
|
77875
|
+
return { isPassed: true, testOutput };
|
|
77876
|
+
}
|
|
77877
|
+
catch (error) {
|
|
77878
|
+
const testOutput = formatUnknownErrorMessage(error);
|
|
77879
|
+
console.error(colors.red('Pre-coding tests failed.'));
|
|
77880
|
+
console.error(testOutput);
|
|
77881
|
+
return { isPassed: false, testOutput };
|
|
77882
|
+
}
|
|
77883
|
+
}
|
|
77884
|
+
|
|
77226
77885
|
/**
|
|
77227
77886
|
* Constant for prompts dir.
|
|
77228
77887
|
*/
|
|
@@ -77250,6 +77909,10 @@ async function runCodexPrompts(providedOptions) {
|
|
|
77250
77909
|
return;
|
|
77251
77910
|
}
|
|
77252
77911
|
const { runner, actualRunnerModel, runnerMetadata } = resolvePromptRunner(options);
|
|
77912
|
+
const promptRunnerIdentity = {
|
|
77913
|
+
harnessName: options.agentName,
|
|
77914
|
+
modelName: actualRunnerModel,
|
|
77915
|
+
};
|
|
77253
77916
|
console.info(colors.green(`Running prompts with ${runner.name}`));
|
|
77254
77917
|
initializeRunUi(uiHandle, runner.name, actualRunnerModel, options);
|
|
77255
77918
|
await initializeRunUiAgentVisual(uiHandle, resolvedCoderAgent === null || resolvedCoderAgent === void 0 ? void 0 : resolvedCoderAgent.agentSource);
|
|
@@ -77264,6 +77927,7 @@ async function runCodexPrompts(providedOptions) {
|
|
|
77264
77927
|
let previousRoundStartTime;
|
|
77265
77928
|
let previousRoundEndTime;
|
|
77266
77929
|
let completedRunCount = 0;
|
|
77930
|
+
let hasRunTestBefore = false;
|
|
77267
77931
|
while (just(true)) {
|
|
77268
77932
|
if (options.autoPull && !options.dryRun) {
|
|
77269
77933
|
await waitForRequestedPause({
|
|
@@ -77276,6 +77940,35 @@ async function runCodexPrompts(providedOptions) {
|
|
|
77276
77940
|
options,
|
|
77277
77941
|
isRichUiEnabled,
|
|
77278
77942
|
});
|
|
77943
|
+
if (!hasRunTestBefore && options.testBefore !== 'no') {
|
|
77944
|
+
await waitForRequestedPause({
|
|
77945
|
+
checkpointLabel: 'loading prompts before running initial tests',
|
|
77946
|
+
phase: 'loading',
|
|
77947
|
+
statusMessage: 'Loading prompts before running initial tests...',
|
|
77948
|
+
});
|
|
77949
|
+
await loadPromptQueueSnapshot({
|
|
77950
|
+
options,
|
|
77951
|
+
isRichUiEnabled,
|
|
77952
|
+
progressDisplay,
|
|
77953
|
+
uiHandle,
|
|
77954
|
+
promptRunnerIdentity,
|
|
77955
|
+
});
|
|
77956
|
+
}
|
|
77957
|
+
if (!hasRunTestBefore) {
|
|
77958
|
+
hasWaitedForStart = await runTestBeforeIfNeeded({
|
|
77959
|
+
options,
|
|
77960
|
+
runner,
|
|
77961
|
+
runnerMetadata,
|
|
77962
|
+
resolvedCoderContext,
|
|
77963
|
+
resolvedAgentSystemMessage,
|
|
77964
|
+
isRichUiEnabled,
|
|
77965
|
+
progressDisplay,
|
|
77966
|
+
uiHandle,
|
|
77967
|
+
waitForRequestedPause,
|
|
77968
|
+
hasWaitedForStart,
|
|
77969
|
+
});
|
|
77970
|
+
hasRunTestBefore = true;
|
|
77971
|
+
}
|
|
77279
77972
|
await waitForRequestedPause({
|
|
77280
77973
|
checkpointLabel: 'loading prompts',
|
|
77281
77974
|
phase: 'loading',
|
|
@@ -77286,6 +77979,7 @@ async function runCodexPrompts(providedOptions) {
|
|
|
77286
77979
|
isRichUiEnabled,
|
|
77287
77980
|
progressDisplay,
|
|
77288
77981
|
uiHandle,
|
|
77982
|
+
promptRunnerIdentity,
|
|
77289
77983
|
});
|
|
77290
77984
|
hasShownUpcomingTasks || (hasShownUpcomingTasks = showUpcomingTasksOnce({
|
|
77291
77985
|
hasShownUpcomingTasks,
|
|
@@ -77293,6 +77987,7 @@ async function runCodexPrompts(providedOptions) {
|
|
|
77293
77987
|
stats: promptQueueSnapshot.stats,
|
|
77294
77988
|
priorityFilter: options.priorityFilter,
|
|
77295
77989
|
isRichUiEnabled,
|
|
77990
|
+
promptRunnerIdentity,
|
|
77296
77991
|
}));
|
|
77297
77992
|
if (!promptQueueSnapshot.nextPrompt) {
|
|
77298
77993
|
if (isEndAfterCurrentPromptRequested(completedRunCount)) {
|
|
@@ -77395,6 +78090,14 @@ async function runCodexPrompts(providedOptions) {
|
|
|
77395
78090
|
* Validates cross-flag constraints before the run starts.
|
|
77396
78091
|
*/
|
|
77397
78092
|
function validateRunCodexPromptOptions(options) {
|
|
78093
|
+
var _a;
|
|
78094
|
+
if (!isTestBeforeMode((_a = options.testBefore) !== null && _a !== void 0 ? _a : 'no')) {
|
|
78095
|
+
throw new NotAllowed(spaceTrim$1(`
|
|
78096
|
+
Invalid ${'`--test-before`'} mode: \`${String(options.testBefore)}\`.
|
|
78097
|
+
|
|
78098
|
+
Use one of: \`no\`, \`yes-and-fail\`, \`yes-and-fix\`.
|
|
78099
|
+
`));
|
|
78100
|
+
}
|
|
77398
78101
|
if (options.allowDestructiveAutoMigrate && !options.autoMigrate) {
|
|
77399
78102
|
throw new DatabaseError(spaceTrim$1(`
|
|
77400
78103
|
Flag \`--allow-destructive-auto-migrate\` requires \`--auto-migrate\`.
|
|
@@ -77465,20 +78168,103 @@ function createRunDisplays(options, runStartDate) {
|
|
|
77465
78168
|
* Normalizes legacy and current priority options into one validated run option shape.
|
|
77466
78169
|
*/
|
|
77467
78170
|
function normalizeRunOptions(options) {
|
|
77468
|
-
var _a, _b, _c, _d, _e;
|
|
78171
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
78172
|
+
const testBefore = (_a = options.testBefore) !== null && _a !== void 0 ? _a : 'no';
|
|
78173
|
+
const normalizedTestCommand = (_b = options.testCommand) === null || _b === void 0 ? void 0 : _b.trim();
|
|
77469
78174
|
const priorityFilter = normalizePriorityFilter({
|
|
77470
78175
|
priority: options.priority,
|
|
77471
|
-
minimumPriority: (
|
|
77472
|
-
maximumPriority: (
|
|
78176
|
+
minimumPriority: (_c = options.minimumPriority) !== null && _c !== void 0 ? _c : (_d = options.priorityFilter) === null || _d === void 0 ? void 0 : _d.minimumPriority,
|
|
78177
|
+
maximumPriority: (_e = options.maximumPriority) !== null && _e !== void 0 ? _e : (_f = options.priorityFilter) === null || _f === void 0 ? void 0 : _f.maximumPriority,
|
|
77473
78178
|
});
|
|
77474
78179
|
return {
|
|
77475
78180
|
...options,
|
|
77476
|
-
|
|
78181
|
+
testBefore,
|
|
78182
|
+
testCommand: normalizedTestCommand || (testBefore === 'no' ? undefined : DEFAULT_CODER_TEST_COMMAND),
|
|
78183
|
+
priority: (_g = priorityFilter.minimumPriority) !== null && _g !== void 0 ? _g : 0,
|
|
77477
78184
|
minimumPriority: priorityFilter.minimumPriority,
|
|
77478
78185
|
maximumPriority: priorityFilter.maximumPriority,
|
|
77479
78186
|
priorityFilter,
|
|
77480
78187
|
};
|
|
77481
78188
|
}
|
|
78189
|
+
/**
|
|
78190
|
+
* Runs the optional pre-coding verification and, when requested, its one repair prompt.
|
|
78191
|
+
*/
|
|
78192
|
+
async function runTestBeforeIfNeeded(options) {
|
|
78193
|
+
const { options: runOptions, runner, runnerMetadata, resolvedCoderContext, resolvedAgentSystemMessage, isRichUiEnabled, progressDisplay, uiHandle, waitForRequestedPause, hasWaitedForStart, } = options;
|
|
78194
|
+
if (runOptions.testBefore === 'no') {
|
|
78195
|
+
return hasWaitedForStart;
|
|
78196
|
+
}
|
|
78197
|
+
if (!runOptions.testCommand) {
|
|
78198
|
+
throw new NotAllowed(spaceTrim$1(`
|
|
78199
|
+
${'`--test-before ' + runOptions.testBefore + '`'} requires a verification command.
|
|
78200
|
+
|
|
78201
|
+
Pass one with ${'`--test <test-command>`'} or use the default ${'`npm test`'} command by providing the mode through the CLI.
|
|
78202
|
+
`));
|
|
78203
|
+
}
|
|
78204
|
+
if (!runOptions.ignoreGitChanges) {
|
|
78205
|
+
await waitForRequestedPause({
|
|
78206
|
+
checkpointLabel: 'checking the git working tree before testing',
|
|
78207
|
+
phase: 'loading',
|
|
78208
|
+
statusMessage: 'Checking the working tree before testing...',
|
|
78209
|
+
});
|
|
78210
|
+
await ensureWorkingTreeClean();
|
|
78211
|
+
}
|
|
78212
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
78213
|
+
const testBeforeResult = await runTestBefore({
|
|
78214
|
+
testCommand: runOptions.testCommand,
|
|
78215
|
+
projectPath: process.cwd(),
|
|
78216
|
+
waitForPauseCheckpoint: waitForRequestedPause,
|
|
78217
|
+
}).finally(() => {
|
|
78218
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
78219
|
+
});
|
|
78220
|
+
if (testBeforeResult.isPassed) {
|
|
78221
|
+
return hasWaitedForStart;
|
|
78222
|
+
}
|
|
78223
|
+
const testOutput = limitTestOutput(testBeforeResult.testOutput);
|
|
78224
|
+
if (runOptions.testBefore === 'yes-and-fail') {
|
|
78225
|
+
throw new NotAllowed(spaceTrim$1((block) => `
|
|
78226
|
+
Pre-coding verification command \`${runOptions.testCommand}\` failed.
|
|
78227
|
+
|
|
78228
|
+
The coding agent was not started because the project was already failing before the first queued prompt.
|
|
78229
|
+
|
|
78230
|
+
### Test results
|
|
78231
|
+
${'```'}
|
|
78232
|
+
${block(testOutput)}
|
|
78233
|
+
${'```'}
|
|
78234
|
+
`));
|
|
78235
|
+
}
|
|
78236
|
+
const repairPrompt = await createTestBeforeRepairPrompt({
|
|
78237
|
+
projectPath: process.cwd(),
|
|
78238
|
+
testCommand: runOptions.testCommand,
|
|
78239
|
+
testOutput,
|
|
78240
|
+
});
|
|
78241
|
+
const repairPromptLabel = buildPromptLabelForDisplay(repairPrompt.file, repairPrompt.section);
|
|
78242
|
+
const updatedHasWaitedForStart = await waitForPromptConfirmationIfNeeded({
|
|
78243
|
+
options: runOptions,
|
|
78244
|
+
nextPrompt: repairPrompt,
|
|
78245
|
+
promptLabel: repairPromptLabel,
|
|
78246
|
+
hasWaitedForStart,
|
|
78247
|
+
isRichUiEnabled,
|
|
78248
|
+
progressDisplay,
|
|
78249
|
+
uiHandle,
|
|
78250
|
+
});
|
|
78251
|
+
// The repair prompt is created in the current worktree so it can be recorded and committed with the repair.
|
|
78252
|
+
// It therefore intentionally uses the regular round here even when the queue itself uses --isolate.
|
|
78253
|
+
await runPromptRound({
|
|
78254
|
+
options: runOptions,
|
|
78255
|
+
runner,
|
|
78256
|
+
runnerMetadata,
|
|
78257
|
+
nextPrompt: repairPrompt,
|
|
78258
|
+
promptLabel: repairPromptLabel,
|
|
78259
|
+
resolvedCoderContext,
|
|
78260
|
+
resolvedAgentSystemMessage,
|
|
78261
|
+
isRichUiEnabled,
|
|
78262
|
+
progressDisplay,
|
|
78263
|
+
uiHandle,
|
|
78264
|
+
waitForRequestedPause,
|
|
78265
|
+
});
|
|
78266
|
+
return updatedHasWaitedForStart;
|
|
78267
|
+
}
|
|
77482
78268
|
/**
|
|
77483
78269
|
* Creates a pause waiter that keeps the progress display and rich UI in sync.
|
|
77484
78270
|
*/
|
|
@@ -77563,7 +78349,7 @@ async function initializeRunUiAgentVisual(uiHandle, agentSource) {
|
|
|
77563
78349
|
* Loads prompt files, updates progress displays, and selects the next runnable prompt.
|
|
77564
78350
|
*/
|
|
77565
78351
|
async function loadPromptQueueSnapshot(options) {
|
|
77566
|
-
const { options: runOptions, isRichUiEnabled, progressDisplay, uiHandle } = options;
|
|
78352
|
+
const { options: runOptions, isRichUiEnabled, progressDisplay, uiHandle, promptRunnerIdentity } = options;
|
|
77567
78353
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentScriptPath(undefined);
|
|
77568
78354
|
const promptFiles = await loadPromptFiles(PROMPTS_DIR$1);
|
|
77569
78355
|
const stats = summarizePrompts(promptFiles, runOptions.priorityFilter);
|
|
@@ -77575,14 +78361,14 @@ async function loadPromptQueueSnapshot(options) {
|
|
|
77575
78361
|
return {
|
|
77576
78362
|
promptFiles,
|
|
77577
78363
|
stats,
|
|
77578
|
-
nextPrompt: findNextTodoPrompt(promptFiles, runOptions.priorityFilter),
|
|
78364
|
+
nextPrompt: findNextTodoPrompt(promptFiles, runOptions.priorityFilter, promptRunnerIdentity),
|
|
77579
78365
|
};
|
|
77580
78366
|
}
|
|
77581
78367
|
/**
|
|
77582
78368
|
* Prints upcoming tasks only on the first loop iteration in plain-console mode.
|
|
77583
78369
|
*/
|
|
77584
78370
|
function showUpcomingTasksOnce(options) {
|
|
77585
|
-
const { hasShownUpcomingTasks, promptFiles, stats, priorityFilter, isRichUiEnabled } = options;
|
|
78371
|
+
const { hasShownUpcomingTasks, promptFiles, stats, priorityFilter, isRichUiEnabled, promptRunnerIdentity } = options;
|
|
77586
78372
|
if (hasShownUpcomingTasks || isRichUiEnabled) {
|
|
77587
78373
|
return true;
|
|
77588
78374
|
}
|
|
@@ -77591,7 +78377,7 @@ function showUpcomingTasksOnce(options) {
|
|
|
77591
78377
|
printPromptsToBeWritten(promptFiles, priorityFilter);
|
|
77592
78378
|
console.info('');
|
|
77593
78379
|
}
|
|
77594
|
-
printUpcomingTasks(listUpcomingTasks(promptFiles, priorityFilter));
|
|
78380
|
+
printUpcomingTasks(listUpcomingTasks(promptFiles, priorityFilter, promptRunnerIdentity));
|
|
77595
78381
|
return true;
|
|
77596
78382
|
}
|
|
77597
78383
|
/**
|
|
@@ -77601,7 +78387,10 @@ function finishWhenNoPromptIsAvailable(promptQueueSnapshot, isRichUiEnabled, uiH
|
|
|
77601
78387
|
if (promptQueueSnapshot.nextPrompt) {
|
|
77602
78388
|
return false;
|
|
77603
78389
|
}
|
|
77604
|
-
if (promptQueueSnapshot.stats.
|
|
78390
|
+
if (promptQueueSnapshot.stats.forAgent > 0) {
|
|
78391
|
+
announceRunCompletion('No prompts match the selected harness or model.', colors.yellow, isRichUiEnabled, uiHandle);
|
|
78392
|
+
}
|
|
78393
|
+
else if (promptQueueSnapshot.stats.toBeWritten > 0) {
|
|
77605
78394
|
announceRunCompletion('No prompts ready for agent.', colors.yellow, isRichUiEnabled, uiHandle);
|
|
77606
78395
|
}
|
|
77607
78396
|
else {
|
|
@@ -77642,9 +78431,16 @@ function finishWhenEndAfterCurrentPromptIsRequested(options) {
|
|
|
77642
78431
|
* Updates the UI status message while waiting for new prompts in keepAlive server mode.
|
|
77643
78432
|
*/
|
|
77644
78433
|
function announceKeepAliveStatus(promptQueueSnapshot, isRichUiEnabled, uiHandle) {
|
|
77645
|
-
|
|
77646
|
-
|
|
77647
|
-
|
|
78434
|
+
let message;
|
|
78435
|
+
if (promptQueueSnapshot.stats.forAgent > 0) {
|
|
78436
|
+
message = 'No prompts match the selected harness or model. Watching for changes...';
|
|
78437
|
+
}
|
|
78438
|
+
else if (promptQueueSnapshot.stats.toBeWritten > 0) {
|
|
78439
|
+
message = 'No prompts ready for agent. Watching for changes...';
|
|
78440
|
+
}
|
|
78441
|
+
else {
|
|
78442
|
+
message = 'All prompts are done. Watching for changes...';
|
|
78443
|
+
}
|
|
77648
78444
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(message);
|
|
77649
78445
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('waiting');
|
|
77650
78446
|
if (!isRichUiEnabled) {
|
|
@@ -77666,7 +78462,7 @@ function announceRunCompletion(message, colorize, isRichUiEnabled, uiHandle) {
|
|
|
77666
78462
|
* Waits for the optional user confirmation before starting the selected prompt.
|
|
77667
78463
|
*/
|
|
77668
78464
|
async function waitForPromptConfirmationIfNeeded(options) {
|
|
77669
|
-
const { options: runOptions, nextPrompt, promptLabel, hasWaitedForStart, isRichUiEnabled, progressDisplay, uiHandle } = options;
|
|
78465
|
+
const { options: runOptions, nextPrompt, promptLabel, hasWaitedForStart, isRichUiEnabled, progressDisplay, uiHandle, } = options;
|
|
77670
78466
|
if (!runOptions.waitForUser) {
|
|
77671
78467
|
return hasWaitedForStart;
|
|
77672
78468
|
}
|
|
@@ -78988,14 +79784,21 @@ async function verifyPrompts(options = DEFAULT_VERIFY_PROMPTS_OPTIONS) {
|
|
|
78988
79784
|
let promptFiles = initialFiles;
|
|
78989
79785
|
const skippedFiles = new Set();
|
|
78990
79786
|
while (true) {
|
|
79787
|
+
// Note: The git synchronization is applied around each single verification, not once per whole run
|
|
79788
|
+
await $pullCoderChanges({ gitSync: normalizedOptions.gitSync });
|
|
79789
|
+
if (normalizedOptions.gitSync.isAutoPullEnabled) {
|
|
79790
|
+
// Note: The pull can bring in prompt file changes, so the queue is reloaded before it is used
|
|
79791
|
+
promptFiles = (await loadPromptFilesForVerification(normalizedOptions)).promptFiles;
|
|
79792
|
+
}
|
|
78991
79793
|
displayPromptOverview(promptFiles);
|
|
78992
79794
|
// First priority: verify files where all prompts are marked as done
|
|
78993
79795
|
const fileWithAllDone = findFileWithAllDonePrompts(promptFiles, skippedFiles);
|
|
78994
79796
|
if (fileWithAllDone) {
|
|
78995
|
-
const
|
|
78996
|
-
if (wasSkipped) {
|
|
79797
|
+
const outcome = await verifyDonePromptsInFile(fileWithAllDone);
|
|
79798
|
+
if (outcome.wasSkipped) {
|
|
78997
79799
|
skippedFiles.add(fileWithAllDone.path);
|
|
78998
79800
|
}
|
|
79801
|
+
await $commitVerificationOutcome(normalizedOptions.gitSync, outcome);
|
|
78999
79802
|
promptFiles = (await loadPromptFilesForVerification(normalizedOptions)).promptFiles;
|
|
79000
79803
|
continue;
|
|
79001
79804
|
}
|
|
@@ -79005,10 +79808,20 @@ async function verifyPrompts(options = DEFAULT_VERIFY_PROMPTS_OPTIONS) {
|
|
|
79005
79808
|
console.info(colors.green('\n✅ All prompts have been verified.'));
|
|
79006
79809
|
break;
|
|
79007
79810
|
}
|
|
79008
|
-
await resolvePrompt(nextPrompt);
|
|
79811
|
+
const outcome = await resolvePrompt(nextPrompt);
|
|
79812
|
+
await $commitVerificationOutcome(normalizedOptions.gitSync, outcome);
|
|
79009
79813
|
promptFiles = (await loadPromptFilesForVerification(normalizedOptions)).promptFiles;
|
|
79010
79814
|
}
|
|
79011
79815
|
}
|
|
79816
|
+
/**
|
|
79817
|
+
* Commits and pushes one applied verification when the git synchronization is enabled.
|
|
79818
|
+
*/
|
|
79819
|
+
async function $commitVerificationOutcome(gitSync, outcome) {
|
|
79820
|
+
if (outcome.commitMessage === null) {
|
|
79821
|
+
return;
|
|
79822
|
+
}
|
|
79823
|
+
await $commitCoderChanges({ gitSync, commitMessage: outcome.commitMessage });
|
|
79824
|
+
}
|
|
79012
79825
|
/**
|
|
79013
79826
|
* Parses supported command-line arguments for the standalone verification script.
|
|
79014
79827
|
*/
|
|
@@ -79016,6 +79829,11 @@ function parseVerifyPromptsCliOptions(args) {
|
|
|
79016
79829
|
return {
|
|
79017
79830
|
reverse: args.includes('--reverse'),
|
|
79018
79831
|
ignore: readRepeatableStringOption(args, '--ignore'),
|
|
79832
|
+
gitSync: {
|
|
79833
|
+
isCommitEnabled: args.includes('--commit'),
|
|
79834
|
+
isAutoPushEnabled: args.includes('--auto-push'),
|
|
79835
|
+
isAutoPullEnabled: args.includes('--auto-pull'),
|
|
79836
|
+
},
|
|
79019
79837
|
};
|
|
79020
79838
|
}
|
|
79021
79839
|
/**
|
|
@@ -79067,10 +79885,11 @@ async function prepareArchiveDirectory() {
|
|
|
79067
79885
|
* Normalizes verification options so the rest of the flow can assume stable defaults.
|
|
79068
79886
|
*/
|
|
79069
79887
|
function normalizeVerifyPromptsOptions(options) {
|
|
79070
|
-
var _a, _b;
|
|
79888
|
+
var _a, _b, _c;
|
|
79071
79889
|
return {
|
|
79072
79890
|
reverse: (_a = options.reverse) !== null && _a !== void 0 ? _a : false,
|
|
79073
79891
|
ignore: normalizeIgnoreValues((_b = options.ignore) !== null && _b !== void 0 ? _b : []),
|
|
79892
|
+
gitSync: (_c = options.gitSync) !== null && _c !== void 0 ? _c : DISABLED_CODER_GIT_SYNC_OPTIONS,
|
|
79074
79893
|
};
|
|
79075
79894
|
}
|
|
79076
79895
|
/**
|
|
@@ -79201,7 +80020,6 @@ function findFileWithAllDonePrompts(promptFiles, skippedFiles) {
|
|
|
79201
80020
|
/**
|
|
79202
80021
|
* Verifies the last done [x] prompt in a file and decides whether to archive it or add a repair prompt.
|
|
79203
80022
|
* Ignores not-ready prompts like [-], [.], [?], etc.
|
|
79204
|
-
* Returns true if the file was skipped, false otherwise.
|
|
79205
80023
|
*/
|
|
79206
80024
|
async function verifyDonePromptsInFile(file) {
|
|
79207
80025
|
const doneCount = file.sections.filter((s) => s.status === 'done').length;
|
|
@@ -79221,31 +80039,44 @@ async function verifyDonePromptsInFile(file) {
|
|
|
79221
80039
|
}
|
|
79222
80040
|
if (!lastDoneSection) {
|
|
79223
80041
|
console.info(colors.gray('No done [x] prompts found in this file.'));
|
|
79224
|
-
return false;
|
|
80042
|
+
return { wasSkipped: false, commitMessage: null };
|
|
79225
80043
|
}
|
|
79226
80044
|
console.info(colors.gray('Verifying the last [x] prompt in the file...\n'));
|
|
79227
80045
|
displayPromptSnippet({ file, section: lastDoneSection });
|
|
79228
80046
|
const decision = await promptForDoneVerification(file, lastDoneSection);
|
|
79229
80047
|
if (decision === 'done') {
|
|
79230
80048
|
await archivePromptFile(file);
|
|
79231
|
-
return false;
|
|
80049
|
+
return { wasSkipped: false, commitMessage: buildArchiveCommitMessage(file) };
|
|
79232
80050
|
}
|
|
79233
80051
|
else if (decision === 'needs-work') {
|
|
79234
80052
|
console.info(colors.yellow('\n⚠️ This prompt needs repair.'));
|
|
79235
80053
|
await appendRepairPrompt(file, lastDoneSection);
|
|
79236
|
-
return false;
|
|
80054
|
+
return { wasSkipped: false, commitMessage: buildRepairCommitMessage(file) };
|
|
79237
80055
|
}
|
|
79238
80056
|
else {
|
|
79239
80057
|
console.info(colors.gray('\n⏩ Skipped, no changes made.'));
|
|
79240
|
-
return true;
|
|
80058
|
+
return { wasSkipped: true, commitMessage: null };
|
|
79241
80059
|
}
|
|
79242
80060
|
}
|
|
80061
|
+
/**
|
|
80062
|
+
* Builds the commit message describing one archived prompt file.
|
|
80063
|
+
*/
|
|
80064
|
+
function buildArchiveCommitMessage(file) {
|
|
80065
|
+
return `✅ Prompt done and archived \`${file.name}\``; // <- $commitCoderChanges({
|
|
80066
|
+
}
|
|
80067
|
+
/**
|
|
80068
|
+
* Builds the commit message describing one appended repair prompt.
|
|
80069
|
+
*/
|
|
80070
|
+
function buildRepairCommitMessage(file) {
|
|
80071
|
+
return `❌ Repair prompt added into \`${file.name}\``; // <- $commitCoderChanges({
|
|
80072
|
+
}
|
|
79243
80073
|
/**
|
|
79244
80074
|
* Asks the user to verify if a done prompt is actually completed.
|
|
79245
80075
|
* Returns 'done' if verified, 'needs-work' if not done, or 'skip' to skip this file.
|
|
79246
80076
|
*/
|
|
79247
80077
|
async function promptForDoneVerification(file, section) {
|
|
79248
80078
|
const promptLabel = buildPromptLabelForDisplay(file, section);
|
|
80079
|
+
const { default: prompts } = await loadPromptsModule();
|
|
79249
80080
|
const response = await prompts({
|
|
79250
80081
|
type: 'select',
|
|
79251
80082
|
name: 'verified',
|
|
@@ -79314,16 +80145,17 @@ async function resolvePrompt(selection) {
|
|
|
79314
80145
|
const decision = await promptForDecision(selection);
|
|
79315
80146
|
if (decision === 'done') {
|
|
79316
80147
|
await archivePromptFile(selection.file);
|
|
80148
|
+
return { wasSkipped: false, commitMessage: buildArchiveCommitMessage(selection.file) };
|
|
79317
80149
|
}
|
|
79318
|
-
|
|
79319
|
-
|
|
79320
|
-
}
|
|
80150
|
+
await appendRepairPrompt(selection.file, selection.section);
|
|
80151
|
+
return { wasSkipped: false, commitMessage: buildRepairCommitMessage(selection.file) };
|
|
79321
80152
|
}
|
|
79322
80153
|
/**
|
|
79323
80154
|
* Presents the interactive decision menu for the current prompt section.
|
|
79324
80155
|
*/
|
|
79325
80156
|
async function promptForDecision(selection) {
|
|
79326
80157
|
const promptLabel = buildPromptLabelForDisplay(selection.file, selection.section);
|
|
80158
|
+
const { default: prompts } = await loadPromptsModule();
|
|
79327
80159
|
const response = await prompts({
|
|
79328
80160
|
type: 'select',
|
|
79329
80161
|
name: 'decision',
|