@promptbook/cli 0.114.0-48 → 0.114.0-49
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 +59 -25
- package/apps/agents-server/tests/e2e/mockSupabaseServer.cjs +79 -2
- package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +12 -2
- package/apps/agents-server/tests/e2e/support/auth.ts +6 -0
- package/esm/index.es.js +1327 -478
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/checks/CheckBeforeMode.d.ts +20 -0
- package/esm/scripts/run-codex-prompts/checks/checkRepairInstructions.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/checks/createCheckBeforeRepairPrompt.d.ts +9 -0
- package/esm/scripts/run-codex-prompts/checks/limitCheckOutput.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/checks/projectCheck.d.ts +26 -0
- package/esm/scripts/run-codex-prompts/checks/projectScriptReferences.d.ts +7 -0
- package/esm/scripts/run-codex-prompts/checks/runCheckBefore.d.ts +26 -0
- package/esm/scripts/run-codex-prompts/checks/runPromptCheckCommand.d.ts +16 -0
- package/esm/scripts/run-codex-prompts/{testing/runPromptWithTestFeedback.d.ts → checks/runPromptWithCheckFeedback.d.ts} +9 -9
- package/esm/scripts/run-codex-prompts/common/resolveCoderContext.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/common/resolveCoderProjectContext.d.ts +17 -0
- package/esm/scripts/run-codex-prompts/common/resolveInlineOrFileText.d.ts +2 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/quoteBashArgument.d.ts +2 -0
- package/esm/scripts/run-codex-prompts/isolation/mapProjectReferenceToWorktree.d.ts +5 -0
- package/esm/scripts/run-codex-prompts/main/runPromptRound.d.ts +3 -1
- package/esm/scripts/run-codex-prompts/prompts/buildPromptLabel.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/buildPromptLabelForDisplay.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +3 -1
- package/esm/scripts/run-codex-prompts/prompts/formatCoderRunSteps.d.ts +2 -2
- package/esm/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/printPromptsToBeWritten.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +2 -0
- package/esm/scripts/run-codex-prompts/team/createCoderTeamPromptRunner.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +1 -1
- package/esm/src/cli/cli-commands/coder/agentCliOptions.d.ts +5 -0
- package/esm/src/cli/cli-commands/coder/coderAgentRole.d.ts +5 -0
- package/esm/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +2 -2
- package/esm/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +3 -2
- package/esm/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/coder/findLegacyCoderCheckCallers.d.ts +5 -0
- package/esm/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +6 -0
- package/esm/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +5 -3
- package/esm/src/cli/cli-commands/coder/planning/runPlanningSession.d.ts +3 -0
- package/esm/src/cli/cli-commands/coder/prepareCoderPackageJsonScripts.d.ts +12 -0
- package/esm/src/cli/cli-commands/coder.d.ts +1 -1
- package/esm/src/cli/cli-commands/common/coderCheckCliOptions.d.ts +21 -0
- package/esm/src/cli/cli-commands/common/coderCheckCliOptions.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/projectCliOptions.d.ts +30 -0
- package/esm/src/cli/cli-commands/common/projectCliOptions.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/promptbook-cli/$checkPromptbookCliInstallations.d.ts +1 -1
- package/esm/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +1 -1
- package/esm/src/cli/cli-commands/common/promptbook-cli/$resolvePromptbookCliInstallations.d.ts +1 -1
- package/esm/src/cli/cli-commands/common/promptbook-cli/$updatePromptbookCliInstallation.d.ts +1 -1
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/_packages/cli.readme.md +15 -0
- package/src/cli/cli-commands/agent/chat.ts +11 -2
- package/src/cli/cli-commands/agent/exec.ts +11 -2
- package/src/cli/cli-commands/agent-folder/init.ts +6 -2
- package/src/cli/cli-commands/agent-folder/initializeAgentRunnerCommand.ts +9 -2
- package/src/cli/cli-commands/coder/add.ts +7 -1
- package/src/cli/cli-commands/coder/agentCliOptions.ts +11 -1
- package/src/cli/cli-commands/coder/coderAgentRole.ts +6 -0
- package/src/cli/cli-commands/coder/coderReferencedArtifacts.ts +3 -3
- package/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.ts +22 -3
- package/src/cli/cli-commands/coder/find-fresh-emoji-tags.ts +3 -0
- package/src/cli/cli-commands/coder/find-refactor-candidates.ts +3 -0
- package/src/cli/cli-commands/coder/find-unwritten.ts +3 -0
- package/src/cli/cli-commands/coder/findLegacyCoderCheckCallers.ts +87 -0
- package/src/cli/cli-commands/coder/generate-boilerplates.ts +3 -0
- package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +6 -7
- package/src/cli/cli-commands/coder/init.ts +8 -2
- package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +16 -4
- package/src/cli/cli-commands/coder/list.ts +6 -1
- package/src/cli/cli-commands/coder/mergeStringRecordJsonFile.ts +14 -4
- package/src/cli/cli-commands/coder/ping.ts +7 -1
- package/src/cli/cli-commands/coder/plan.ts +17 -5
- package/src/cli/cli-commands/coder/planning/README.md +5 -3
- package/src/cli/cli-commands/coder/planning/fixtures/coding.cjs +22 -0
- package/src/cli/cli-commands/coder/planning/runPlanningSession.ts +14 -3
- package/src/cli/cli-commands/coder/planning/savePlanningChanges.ts +1 -3
- package/src/cli/cli-commands/coder/prepareCoderPackageJsonScripts.ts +304 -0
- package/src/cli/cli-commands/coder/printInitializationSummary.ts +5 -1
- package/src/cli/cli-commands/coder/promptsReadmeTemplate.ts +31 -13
- package/src/cli/cli-commands/coder/run.ts +31 -65
- package/src/cli/cli-commands/coder/server.ts +21 -39
- package/src/cli/cli-commands/coder/verify.ts +3 -0
- package/src/cli/cli-commands/coder.ts +2 -2
- package/src/cli/cli-commands/common/coderCheckCliOptions.ts +107 -0
- package/src/cli/cli-commands/common/projectCliOptions.ts +78 -0
- package/src/cli/cli-commands/common/promptbook-cli/$checkPromptbookCliInstallations.ts +4 -2
- package/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.ts +3 -2
- package/src/cli/cli-commands/common/promptbook-cli/$resolvePromptbookCliInstallations.ts +8 -4
- package/src/cli/cli-commands/common/promptbook-cli/$updatePromptbookCliInstallation.ts +5 -2
- package/src/cli/cli-commands/common/validateCoderRunOptions.ts +12 -5
- package/src/cli/cli-commands/common/workspaceRepository.ts +7 -19
- package/src/cli/cli-commands/common/workspaceRepositoryCliOptions.ts +2 -0
- package/src/execution/translation/automatic-translate/translateMessages.ts +1 -3
- package/src/other/templates/getTemplatesPipelineCollection.ts +1074 -1210
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +1324 -475
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/checks/CheckBeforeMode.d.ts +20 -0
- package/umd/scripts/run-codex-prompts/checks/checkRepairInstructions.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/checks/createCheckBeforeRepairPrompt.d.ts +9 -0
- package/umd/scripts/run-codex-prompts/checks/limitCheckOutput.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/checks/projectCheck.d.ts +26 -0
- package/umd/scripts/run-codex-prompts/checks/projectScriptReferences.d.ts +7 -0
- package/umd/scripts/run-codex-prompts/checks/runCheckBefore.d.ts +26 -0
- package/umd/scripts/run-codex-prompts/checks/runPromptCheckCommand.d.ts +16 -0
- package/umd/scripts/run-codex-prompts/{testing/runPromptWithTestFeedback.d.ts → checks/runPromptWithCheckFeedback.d.ts} +9 -9
- package/umd/scripts/run-codex-prompts/common/resolveCoderContext.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/common/resolveCoderProjectContext.d.ts +17 -0
- package/umd/scripts/run-codex-prompts/common/resolveInlineOrFileText.d.ts +2 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/quoteBashArgument.d.ts +2 -0
- package/umd/scripts/run-codex-prompts/isolation/mapProjectReferenceToWorktree.d.ts +5 -0
- package/umd/scripts/run-codex-prompts/main/runPromptRound.d.ts +3 -1
- package/umd/scripts/run-codex-prompts/prompts/buildPromptLabel.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/prompts/buildPromptLabelForDisplay.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +3 -1
- package/umd/scripts/run-codex-prompts/prompts/formatCoderRunSteps.d.ts +2 -2
- package/umd/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/prompts/printPromptsToBeWritten.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/server/buildCoderServerPromptResponse.d.ts +2 -0
- package/umd/scripts/run-codex-prompts/team/createCoderTeamPromptRunner.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +1 -1
- package/umd/src/cli/cli-commands/coder/agentCliOptions.d.ts +5 -0
- package/umd/src/cli/cli-commands/coder/coderAgentRole.d.ts +5 -0
- package/umd/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +2 -2
- package/umd/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +3 -2
- package/umd/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/coder/findLegacyCoderCheckCallers.d.ts +5 -0
- package/umd/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +6 -0
- package/umd/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +5 -3
- package/umd/src/cli/cli-commands/coder/planning/runPlanningSession.d.ts +3 -0
- package/umd/src/cli/cli-commands/coder/prepareCoderPackageJsonScripts.d.ts +12 -0
- package/umd/src/cli/cli-commands/coder.d.ts +1 -1
- package/umd/src/cli/cli-commands/common/coderCheckCliOptions.d.ts +21 -0
- package/umd/src/cli/cli-commands/common/coderCheckCliOptions.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/projectCliOptions.d.ts +30 -0
- package/umd/src/cli/cli-commands/common/projectCliOptions.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/promptbook-cli/$checkPromptbookCliInstallations.d.ts +1 -1
- package/umd/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +1 -1
- package/umd/src/cli/cli-commands/common/promptbook-cli/$resolvePromptbookCliInstallations.d.ts +1 -1
- package/umd/src/cli/cli-commands/common/promptbook-cli/$updatePromptbookCliInstallation.d.ts +1 -1
- package/umd/src/version.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +0 -16
- package/esm/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +0 -9
- package/esm/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +0 -4
- package/esm/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +0 -14
- package/esm/scripts/run-codex-prompts/testing/runTestBefore.d.ts +0 -24
- package/umd/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +0 -16
- package/umd/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +0 -9
- package/umd/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +0 -4
- package/umd/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +0 -14
- package/umd/scripts/run-codex-prompts/testing/runTestBefore.d.ts +0 -24
package/umd/index.umd.js
CHANGED
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
* @generated
|
|
59
59
|
* @see https://github.com/webgptorg/promptbook
|
|
60
60
|
*/
|
|
61
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-
|
|
61
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-49';
|
|
62
62
|
/**
|
|
63
63
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
64
64
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -1753,6 +1753,56 @@
|
|
|
1753
1753
|
return command.help();
|
|
1754
1754
|
}
|
|
1755
1755
|
|
|
1756
|
+
/**
|
|
1757
|
+
* Registers project selection without capturing a directory during command registration.
|
|
1758
|
+
* @private internal CLI registration helper
|
|
1759
|
+
*/
|
|
1760
|
+
function addProjectPathOption(command) {
|
|
1761
|
+
command.option('--path <directory>', 'Project directory (default: invocation current directory); relative paths start there');
|
|
1762
|
+
}
|
|
1763
|
+
/**
|
|
1764
|
+
* Registers additional context independently of primary-agent selection.
|
|
1765
|
+
* @private internal CLI registration helper
|
|
1766
|
+
*/
|
|
1767
|
+
function addProjectContextOption(command) {
|
|
1768
|
+
command.option('--context <context-or-file>', 'Additional instructions (default: project AGENTS.md); inline text or a project-relative file replaces the default; an empty value disables it');
|
|
1769
|
+
}
|
|
1770
|
+
/**
|
|
1771
|
+
* Captures an invocation's directory at action time. No process-global state is changed.
|
|
1772
|
+
* @private internal CLI normalization helper
|
|
1773
|
+
*/
|
|
1774
|
+
function normalizeProjectCliOptions(options, invocationDirectory = process.cwd()) {
|
|
1775
|
+
const selectedPath = options.path;
|
|
1776
|
+
if (selectedPath !== undefined && !selectedPath.trim()) {
|
|
1777
|
+
throw new EnvironmentMismatchError(spaceTrim('Pass a non-empty project directory in `--path`, or omit it to use the current directory.'));
|
|
1778
|
+
}
|
|
1779
|
+
return { projectDirectory: path.resolve(invocationDirectory, selectedPath !== null && selectedPath !== void 0 ? selectedPath : '.') };
|
|
1780
|
+
}
|
|
1781
|
+
/**
|
|
1782
|
+
* Validates the selected directory before any setup writes, without selecting an enclosing Git root.
|
|
1783
|
+
* @private shared project resolution for CLI services
|
|
1784
|
+
*/
|
|
1785
|
+
async function resolveProjectDirectory(projectDirectory) {
|
|
1786
|
+
const requestedPath = path.resolve(projectDirectory);
|
|
1787
|
+
try {
|
|
1788
|
+
const projectPath = await promises.realpath(requestedPath);
|
|
1789
|
+
if (!(await promises.stat(projectPath)).isDirectory()) {
|
|
1790
|
+
throw new EnvironmentMismatchError(spaceTrim(`Project path \`${requestedPath}\` is not a directory.`));
|
|
1791
|
+
}
|
|
1792
|
+
await promises.access(projectPath, fs.constants.R_OK | fs.constants.X_OK);
|
|
1793
|
+
return projectPath;
|
|
1794
|
+
}
|
|
1795
|
+
catch (error) {
|
|
1796
|
+
throw new EnvironmentMismatchError(spaceTrim(`
|
|
1797
|
+
Cannot access project directory \`${requestedPath}\`.
|
|
1798
|
+
Check that it exists, is a directory, and is readable and searchable; correct \`--path\` before retrying.
|
|
1799
|
+
|
|
1800
|
+
${error instanceof Error ? error.message : String(error)}
|
|
1801
|
+
`));
|
|
1802
|
+
}
|
|
1803
|
+
}
|
|
1804
|
+
// Note: [💞] Shared project registration and resolution helpers.
|
|
1805
|
+
|
|
1756
1806
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
1757
1807
|
/**
|
|
1758
1808
|
* All CLI harness names supported by `CliAgent` and `ptbk agent exec`.
|
|
@@ -2112,15 +2162,18 @@
|
|
|
2112
2162
|
command.requiredOption('--agent <agent-book-path>', 'Path to the agent .book file');
|
|
2113
2163
|
addPromptRunnerSelectionOptions(command);
|
|
2114
2164
|
addPromptRunnerRuntimeOptions(command);
|
|
2115
|
-
command
|
|
2165
|
+
addProjectPathOption(command);
|
|
2166
|
+
addProjectContextOption(command);
|
|
2116
2167
|
command.action(handleActionErrors(async (cliOptions, commandProgram) => {
|
|
2168
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
2169
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
2117
2170
|
const options = cliOptions;
|
|
2118
2171
|
const runnerOptions = normalizeAgentCommandRunnerOptions(options, commandProgram);
|
|
2119
2172
|
const { runAgentChat } = await Promise.resolve().then(function () { return runAgentChat$1; });
|
|
2120
2173
|
await runAgentChat({
|
|
2121
2174
|
agentPath: resolveRequiredAgentPath(options),
|
|
2122
2175
|
context: options.context,
|
|
2123
|
-
currentWorkingDirectory:
|
|
2176
|
+
currentWorkingDirectory: projectPath,
|
|
2124
2177
|
...runnerOptions,
|
|
2125
2178
|
});
|
|
2126
2179
|
}));
|
|
@@ -2146,8 +2199,11 @@
|
|
|
2146
2199
|
command.requiredOption('--message <message>', 'User message to send to the agent');
|
|
2147
2200
|
addPromptRunnerSelectionOptions(command);
|
|
2148
2201
|
addPromptRunnerRuntimeOptions(command);
|
|
2149
|
-
command
|
|
2202
|
+
addProjectPathOption(command);
|
|
2203
|
+
addProjectContextOption(command);
|
|
2150
2204
|
command.action(handleActionErrors(async (cliOptions, commandProgram) => {
|
|
2205
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
2206
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
2151
2207
|
const options = cliOptions;
|
|
2152
2208
|
const runnerOptions = normalizeAgentCommandRunnerOptions(options, commandProgram);
|
|
2153
2209
|
const { runAgentExec } = await Promise.resolve().then(function () { return runAgentExec$1; });
|
|
@@ -2155,7 +2211,7 @@
|
|
|
2155
2211
|
agentPath: resolveRequiredAgentPath(options),
|
|
2156
2212
|
context: options.context,
|
|
2157
2213
|
message: resolveRequiredAgentMessage(options),
|
|
2158
|
-
currentWorkingDirectory:
|
|
2214
|
+
currentWorkingDirectory: projectPath,
|
|
2159
2215
|
...runnerOptions,
|
|
2160
2216
|
});
|
|
2161
2217
|
}));
|
|
@@ -2459,8 +2515,11 @@
|
|
|
2459
2515
|
- ${AGENT_BOOK_FILE_PATH}
|
|
2460
2516
|
- ${AGENT_BOOK_LANGUAGE_MANUAL_FILE_PATH.replace(/\\/gu, '/')}
|
|
2461
2517
|
`));
|
|
2462
|
-
command
|
|
2463
|
-
|
|
2518
|
+
addProjectPathOption(command);
|
|
2519
|
+
command.action(handleActionErrors(async (cliOptions) => {
|
|
2520
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
2521
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
2522
|
+
const summary = await initializeAgentProjectConfiguration(projectPath);
|
|
2464
2523
|
printAgentInitializationSummary(summary);
|
|
2465
2524
|
}));
|
|
2466
2525
|
}
|
|
@@ -2515,15 +2574,21 @@
|
|
|
2515
2574
|
`));
|
|
2516
2575
|
addPromptRunnerSelectionOptions(command);
|
|
2517
2576
|
addPromptRunnerExecutionOptions(command);
|
|
2577
|
+
addProjectPathOption(command);
|
|
2518
2578
|
(_a = options.configureCommand) === null || _a === void 0 ? void 0 : _a.call(options, command);
|
|
2519
2579
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
2520
|
-
const
|
|
2580
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
2581
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
2582
|
+
const runOptions = {
|
|
2583
|
+
...createAgentRunOptionsFromCliOptions(cliOptions),
|
|
2584
|
+
projectPath,
|
|
2585
|
+
};
|
|
2521
2586
|
const execute = await options.loadExecutor();
|
|
2522
2587
|
if (options.executionMode === 'watch') {
|
|
2523
2588
|
const { runPersistentAgentWatch } = await Promise.resolve().then(function () { return runPersistentAgentWatch$1; });
|
|
2524
2589
|
await runPersistentAgentWatch({
|
|
2525
2590
|
commandDisplayName: `ptbk agent-folder ${options.commandName}`,
|
|
2526
|
-
logDirectoryPath:
|
|
2591
|
+
logDirectoryPath: projectPath,
|
|
2527
2592
|
runWatch: async () => {
|
|
2528
2593
|
await execute(runOptions);
|
|
2529
2594
|
},
|
|
@@ -24757,7 +24822,7 @@
|
|
|
24757
24822
|
* Distinguishes prompt-runner and verification temp shells in the shared runtime log.
|
|
24758
24823
|
*/
|
|
24759
24824
|
function describeTempScriptKind(scriptPath) {
|
|
24760
|
-
return scriptPath.toLowerCase().endsWith('.
|
|
24825
|
+
return scriptPath.toLowerCase().endsWith('.check.sh') ? 'check shell' : 'runner shell';
|
|
24761
24826
|
}
|
|
24762
24827
|
|
|
24763
24828
|
/**
|
|
@@ -24960,28 +25025,44 @@
|
|
|
24960
25025
|
/**
|
|
24961
25026
|
* Handles process exit and resolves or rejects accordingly.
|
|
24962
25027
|
*/
|
|
24963
|
-
const handleExit = (code) => {
|
|
25028
|
+
const handleExit = (code, signal) => {
|
|
24964
25029
|
var _a;
|
|
24965
25030
|
if ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted) {
|
|
24966
25031
|
settleWithLog('cancelled', () => reject(options.signal.reason), options.signal.reason);
|
|
24967
25032
|
return;
|
|
24968
25033
|
}
|
|
24969
|
-
if (code === 0) {
|
|
24970
|
-
settleWithLog('succeeded', () =>
|
|
25034
|
+
if (code === 0 && !signal) {
|
|
25035
|
+
settleWithLog('succeeded', () => {
|
|
25036
|
+
var _a;
|
|
25037
|
+
// Cancellation can arrive while the runtime log footer is being flushed.
|
|
25038
|
+
if ((_a = options.signal) === null || _a === void 0 ? void 0 : _a.aborted)
|
|
25039
|
+
reject(options.signal.reason);
|
|
25040
|
+
else
|
|
25041
|
+
resolve(_spaceTrim.spaceTrim(output));
|
|
25042
|
+
});
|
|
24971
25043
|
return;
|
|
24972
25044
|
}
|
|
24973
|
-
const failure = new
|
|
24974
|
-
|
|
25045
|
+
const failure = new NotAllowed(_spaceTrim.spaceTrim((block) => `
|
|
25046
|
+
Command "bash ${scriptPathPosix}" exited with code ${code !== null && code !== void 0 ? code : 'unknown'}${signal ? ` and signal ${signal}` : ''}.
|
|
25047
|
+
${block(output)}
|
|
25048
|
+
`));
|
|
25049
|
+
settleWithLog(`failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}${signal ? ` and signal ${signal}` : ''}`, () => reject(failure), failure);
|
|
24975
25050
|
};
|
|
24976
25051
|
// Wait for `close`, not only `exit`, because the Bash wrapper can still be flushing its tee process
|
|
24977
25052
|
// substitutions after the direct shell exits.
|
|
24978
25053
|
commandProcess.on('close', handleExit);
|
|
24979
25054
|
commandProcess.on('disconnect', () => {
|
|
24980
|
-
const failure = new
|
|
25055
|
+
const failure = new NotAllowed(_spaceTrim.spaceTrim((block) => `
|
|
25056
|
+
Command "bash ${scriptPathPosix}" disconnected.
|
|
25057
|
+
${block(output)}
|
|
25058
|
+
`));
|
|
24981
25059
|
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
24982
25060
|
});
|
|
24983
25061
|
commandProcess.on('error', (error) => {
|
|
24984
|
-
const failure = new
|
|
25062
|
+
const failure = new NotAllowed(_spaceTrim.spaceTrim((block) => `
|
|
25063
|
+
Command "bash ${scriptPathPosix}" failed: ${error.message}
|
|
25064
|
+
${block(output)}
|
|
25065
|
+
`));
|
|
24985
25066
|
settleWithLog('failed before completion', () => reject(failure), failure);
|
|
24986
25067
|
});
|
|
24987
25068
|
/** Reuses the process-tree terminator; settlement waits for stream closure and the trace footer. */
|
|
@@ -26437,6 +26518,11 @@
|
|
|
26437
26518
|
}
|
|
26438
26519
|
}
|
|
26439
26520
|
|
|
26521
|
+
/** Quotes one literal argument, including spaces and shell metacharacters, for a generated Bash script. */
|
|
26522
|
+
function quoteBashArgument(value) {
|
|
26523
|
+
return `'${value.replace(/'/gu, "'\\''")}'`;
|
|
26524
|
+
}
|
|
26525
|
+
|
|
26440
26526
|
/**
|
|
26441
26527
|
* Builds the shell script that runs GitHub Copilot CLI with the prompt and coding context.
|
|
26442
26528
|
*/
|
|
@@ -26446,7 +26532,7 @@
|
|
|
26446
26532
|
const modelArgument = options.model ? ` --model ${options.model}` : '';
|
|
26447
26533
|
const thinkingLevelArgument = options.thinkingLevel ? ` --reasoning-effort ${options.thinkingLevel}` : '';
|
|
26448
26534
|
return spaceTrim((block) => `
|
|
26449
|
-
cd
|
|
26535
|
+
cd ${quoteBashArgument(projectPath)}
|
|
26450
26536
|
|
|
26451
26537
|
if [ -f .env ]; then
|
|
26452
26538
|
set -a
|
|
@@ -26887,7 +26973,7 @@
|
|
|
26887
26973
|
...(options.isMachineReadableProgressEnabled ? [' --json \\'] : []),
|
|
26888
26974
|
' --local-provider none \\',
|
|
26889
26975
|
` --sandbox ${options.sandbox} \\`,
|
|
26890
|
-
` -C ${projectPath} \\`,
|
|
26976
|
+
` -C ${quoteBashArgument(projectPath)} \\`,
|
|
26891
26977
|
' --skip-git-repo-check \\',
|
|
26892
26978
|
` <<'${delimiter}'`,
|
|
26893
26979
|
'',
|
|
@@ -29223,7 +29309,7 @@
|
|
|
29223
29309
|
...buildOptionalSessionRow('Server', options.config.serverUrl
|
|
29224
29310
|
? buildTerminalUrlLink(options.config.serverUrl, bodyWidth - SESSION_LABEL_WIDTH - 1)
|
|
29225
29311
|
: undefined),
|
|
29226
|
-
...buildOptionalSessionRow('
|
|
29312
|
+
...buildOptionalSessionRow('Check', options.config.checkCommand),
|
|
29227
29313
|
];
|
|
29228
29314
|
return [
|
|
29229
29315
|
{
|
|
@@ -31717,7 +31803,7 @@
|
|
|
31717
31803
|
return {
|
|
31718
31804
|
dryRun: false,
|
|
31719
31805
|
context: undefined,
|
|
31720
|
-
|
|
31806
|
+
checkCommand: undefined,
|
|
31721
31807
|
preserveLogs: false,
|
|
31722
31808
|
noUi: options.noUi,
|
|
31723
31809
|
thinkingLevel: options.thinkingLevel,
|
|
@@ -32819,40 +32905,207 @@
|
|
|
32819
32905
|
}
|
|
32820
32906
|
|
|
32821
32907
|
/**
|
|
32822
|
-
* Maximum amount of
|
|
32908
|
+
* Maximum amount of check output embedded into an agent prompt.
|
|
32909
|
+
*/
|
|
32910
|
+
const MAX_CHECK_OUTPUT_CHARS = 12000;
|
|
32911
|
+
/**
|
|
32912
|
+
* Limits check output while keeping the end of the output, where check tools usually print the failure summary.
|
|
32913
|
+
*/
|
|
32914
|
+
function limitCheckOutput(checkOutput) {
|
|
32915
|
+
const normalizedCheckOutput = checkOutput.trim();
|
|
32916
|
+
if (normalizedCheckOutput.length <= MAX_CHECK_OUTPUT_CHARS) {
|
|
32917
|
+
return normalizedCheckOutput;
|
|
32918
|
+
}
|
|
32919
|
+
return `[..., check output truncated to the last ${MAX_CHECK_OUTPUT_CHARS} characters...]\n${normalizedCheckOutput.slice(-MAX_CHECK_OUTPUT_CHARS)}`;
|
|
32920
|
+
}
|
|
32921
|
+
|
|
32922
|
+
/**
|
|
32923
|
+
* Modes supported by `ptbk coder run --check-before`.
|
|
32924
|
+
*/
|
|
32925
|
+
const CHECK_BEFORE_MODE_VALUES = ['no', 'yes-and-fail', 'yes-and-fix'];
|
|
32926
|
+
/**
|
|
32927
|
+
* Default check command used when a pre-coding mode is enabled without an explicit `--check` command.
|
|
32928
|
+
*/
|
|
32929
|
+
const DEFAULT_CODER_CHECK_COMMAND = 'npm run check';
|
|
32930
|
+
/**
|
|
32931
|
+
* Resolves the shared command without enabling checks when both command and preflight mode are absent.
|
|
32932
|
+
*/
|
|
32933
|
+
function resolveCoderCheckCommand(checkCommand, checkBefore = 'no') {
|
|
32934
|
+
return checkCommand !== null && checkCommand !== void 0 ? checkCommand : (checkBefore === 'no' ? undefined : DEFAULT_CODER_CHECK_COMMAND);
|
|
32935
|
+
}
|
|
32936
|
+
/**
|
|
32937
|
+
* Checks whether a value is a supported `--check-before` mode.
|
|
32938
|
+
*/
|
|
32939
|
+
function isCheckBeforeMode(value) {
|
|
32940
|
+
return CHECK_BEFORE_MODE_VALUES.includes(value);
|
|
32941
|
+
}
|
|
32942
|
+
|
|
32943
|
+
/** Conventional root command boundaries, including subshells and environment assignments. */
|
|
32944
|
+
const SCRIPT_COMMAND_PREFIX = String.raw `(?:^|&&|\|\||;|\n|[()])\s*(?:(?:env\s+)?[A-Za-z_]\w*=(?:[^\s'";&|()]+|"[^"]*"|'[^']*')\s+)*`;
|
|
32945
|
+
/** Package-manager options which do not select a different directory or workspace. */
|
|
32946
|
+
const QUIET_OPTIONS = String.raw `(?:(?:--silent|--quiet|-s|-q)\s+)*`;
|
|
32947
|
+
/** Quoted script names preserve spaces, while unquoted names use conventional npm identifier characters. */
|
|
32948
|
+
const SCRIPT_NAME = String.raw `(?:(["'])([^"'\r\n]+)\1|([\w:.-]+))(?=\s|$|[;&|()])`;
|
|
32949
|
+
/** Quoted payloads and escaped characters are opaque to this configuration inspection. */
|
|
32950
|
+
const OPAQUE_ARGUMENT = String.raw `"(?:\\.|[^"\\])*"|'[^']*'|\\[\s\S]`;
|
|
32951
|
+
/** Only references before a conventional directory change can confidently belong to the root package. */
|
|
32952
|
+
const DIRECTORY_CHANGE_COMMAND = new RegExp(`${SCRIPT_COMMAND_PREFIX}(?:cd|pushd|popd)(?=\\s|$)|(?<argument>${OPAQUE_ARGUMENT})`, 'gu');
|
|
32953
|
+
/** Arguments up to the next conventional command boundary, preserving quoted payloads as opaque text. */
|
|
32954
|
+
const SCRIPT_ARGUMENTS = new RegExp(String.raw `^(?:${OPAQUE_ARGUMENT}|[^;&|\n()'"\\])*`, 'u');
|
|
32955
|
+
/** Package-manager options that select validation from a different directory or workspace. */
|
|
32956
|
+
const PROJECT_OVERRIDE_OPTION = /\s(?:--prefix|--dir|--cwd|-C|--workspace|--workspaces|-w|--filter)(?:\s|=|$)/u;
|
|
32957
|
+
/**
|
|
32958
|
+
* Reads conventional npm/pnpm/yarn script references for configuration inspection.
|
|
32959
|
+
* Commands are still executed verbatim by the existing shell runner; this helper neither parses nor rewrites shells.
|
|
32960
|
+
* Options selecting other workspaces remain opaque so their scripts are not mistaken for root validation.
|
|
32961
|
+
* Inspection stops at the first directory change; quoted examples do not change the inspected workspace.
|
|
32823
32962
|
*/
|
|
32824
|
-
|
|
32963
|
+
function projectScriptReferences(command) {
|
|
32964
|
+
var _a;
|
|
32965
|
+
const directoryChange = [...command.matchAll(DIRECTORY_CHANGE_COMMAND)].find((match) => { var _a; return ((_a = match.groups) === null || _a === void 0 ? void 0 : _a.argument) === undefined; });
|
|
32966
|
+
if (directoryChange)
|
|
32967
|
+
command = command.slice(0, directoryChange.index);
|
|
32968
|
+
const references = [
|
|
32969
|
+
...command.matchAll(new RegExp(`${SCRIPT_COMMAND_PREFIX}(?:npm|pnpm|yarn)\\s+${QUIET_OPTIONS}(?:run(?:-script)?\\s+${QUIET_OPTIONS}${SCRIPT_NAME}|(?:test|t)(?=\\s|$|[;&|()]))` +
|
|
32970
|
+
`|(?<argument>${OPAQUE_ARGUMENT})`, 'gu')),
|
|
32971
|
+
]
|
|
32972
|
+
.filter((match) => isRootProjectScriptReference(command, match))
|
|
32973
|
+
.map((match) => { var _a, _b; return (_b = (_a = match[2]) !== null && _a !== void 0 ? _a : match[3]) !== null && _b !== void 0 ? _b : 'test'; });
|
|
32974
|
+
for (const match of command.matchAll(new RegExp(`${SCRIPT_COMMAND_PREFIX}(?:pnpm|yarn)\\s+${QUIET_OPTIONS}(?!run\\b|-)${SCRIPT_NAME}` +
|
|
32975
|
+
`|(?<argument>${OPAQUE_ARGUMENT})`, 'gu')))
|
|
32976
|
+
if (isRootProjectScriptReference(command, match))
|
|
32977
|
+
references.push(((_a = match[2]) !== null && _a !== void 0 ? _a : match[3]));
|
|
32978
|
+
return [...new Set(references)];
|
|
32979
|
+
}
|
|
32980
|
+
/** Excludes quoted examples and package-manager directory overrides without altering the executed command. */
|
|
32981
|
+
function isRootProjectScriptReference(command, match) {
|
|
32982
|
+
var _a, _b, _c, _d;
|
|
32983
|
+
if (((_a = match.groups) === null || _a === void 0 ? void 0 : _a.argument) !== undefined)
|
|
32984
|
+
return false;
|
|
32985
|
+
const argumentsText = (_c = (_b = command.slice(match.index + match[0].length).match(SCRIPT_ARGUMENTS)) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : '';
|
|
32986
|
+
// Flags after npm's `--` separator belong to the leaf tool, rather than the package manager.
|
|
32987
|
+
const packageManagerArguments = (_d = argumentsText.split(/\s--(?:\s|$)/u)[0]) !== null && _d !== void 0 ? _d : '';
|
|
32988
|
+
return !PROJECT_OVERRIDE_OPTION.test(packageManagerArguments);
|
|
32989
|
+
}
|
|
32990
|
+
|
|
32825
32991
|
/**
|
|
32826
|
-
*
|
|
32992
|
+
* Failing setup placeholder used only when initialization finds no usable project validation scripts.
|
|
32827
32993
|
*/
|
|
32828
|
-
|
|
32829
|
-
|
|
32830
|
-
|
|
32831
|
-
|
|
32994
|
+
const CHECK_SETUP_PLACEHOLDER_COMMAND = `node -e "console.error('Configure package.json scripts.check with project validation commands before running Coder.'); process.exit(1)"`;
|
|
32995
|
+
/** Retired generated script names inspected only to report stale caller configuration. */
|
|
32996
|
+
const LEGACY_CHECK_SCRIPT_NAMES$1 = new Set(['test-for-ptbk-coder', 'check-for-ptbk-coder']);
|
|
32997
|
+
/**
|
|
32998
|
+
* A missing or unconfigured project check needs project-owner setup, rather than model repair retries.
|
|
32999
|
+
*/
|
|
33000
|
+
class CoderCheckSetupError extends NotAllowed {
|
|
33001
|
+
/** Creates an actionable project check setup error. */
|
|
33002
|
+
constructor(details) {
|
|
33003
|
+
super(_spaceTrim.spaceTrim(`
|
|
33004
|
+
Project check is not configured: ${details}
|
|
33005
|
+
|
|
33006
|
+
Configure the selected validation scripts in \`package.json\`. The canonical aggregate is \`scripts.check\`, invoked as \`${DEFAULT_CODER_CHECK_COMMAND}\`.
|
|
33007
|
+
Coder will not replace missing validation with a successful placeholder or tests alone.
|
|
33008
|
+
`));
|
|
33009
|
+
Object.setPrototypeOf(this, CoderCheckSetupError.prototype);
|
|
32832
33010
|
}
|
|
32833
|
-
return `[..., test output truncated to the last ${MAX_TEST_OUTPUT_CHARS} characters...]\n${normalizedTestOutput.slice(-MAX_TEST_OUTPUT_CHARS)}`;
|
|
32834
33011
|
}
|
|
33012
|
+
/**
|
|
33013
|
+
* Detects the generated setup placeholder and the conventional npm unconfigured-test placeholder.
|
|
33014
|
+
*/
|
|
33015
|
+
function isCheckSetupRequired(command) {
|
|
33016
|
+
return (!command.trim() ||
|
|
33017
|
+
command.includes('Configure package.json scripts.check') ||
|
|
33018
|
+
/no test specified/iu.test(command));
|
|
33019
|
+
}
|
|
33020
|
+
/**
|
|
33021
|
+
* Inspects root project check references before an initial check or repair loop can start.
|
|
33022
|
+
* Flags and shell composition do not bypass setup validation; execution still uses the existing shell runner.
|
|
33023
|
+
*/
|
|
33024
|
+
async function assertProjectCheckIsConfigured(command, projectPath) {
|
|
33025
|
+
var _a, _b;
|
|
33026
|
+
if (!command)
|
|
33027
|
+
return;
|
|
33028
|
+
const references = projectScriptReferences(command);
|
|
33029
|
+
if (references.length === 0)
|
|
33030
|
+
return;
|
|
33031
|
+
let packageJson;
|
|
33032
|
+
try {
|
|
33033
|
+
packageJson = JSON.parse(await promises.readFile(path.join(projectPath, 'package.json'), 'utf-8'));
|
|
33034
|
+
}
|
|
33035
|
+
catch (error) {
|
|
33036
|
+
throw new CoderCheckSetupError(`cannot read package.json (${error instanceof Error ? error.message : String(error)}).`);
|
|
33037
|
+
}
|
|
33038
|
+
for (const reference of references) {
|
|
33039
|
+
if (LEGACY_CHECK_SCRIPT_NAMES$1.has(reference) && ((_a = packageJson === null || packageJson === void 0 ? void 0 : packageJson.scripts) === null || _a === void 0 ? void 0 : _a[reference]) === undefined) {
|
|
33040
|
+
throw new CoderCheckSetupError(`scripts.${reference} is missing and is no longer initialized by Coder. Update this caller to \`--check "${DEFAULT_CODER_CHECK_COMMAND}"\`; no compatibility alias is generated.`);
|
|
33041
|
+
}
|
|
33042
|
+
assertProjectCheckScriptsAreConfigured((_b = packageJson === null || packageJson === void 0 ? void 0 : packageJson.scripts) !== null && _b !== void 0 ? _b : {}, reference);
|
|
33043
|
+
}
|
|
33044
|
+
}
|
|
33045
|
+
/**
|
|
33046
|
+
* Validates the project-owned check definition without running commands or changing its scope.
|
|
33047
|
+
* Initialization and execution use this same setup diagnostic for missing leaves and recursive callers.
|
|
33048
|
+
*/
|
|
33049
|
+
function assertProjectCheckScriptsAreConfigured(scripts, name = 'check') {
|
|
33050
|
+
assertReferencedScriptsAreConfigured(name, scripts, new Set());
|
|
33051
|
+
}
|
|
33052
|
+
/** Detects missing/placeholder leaf validation and recursive npm callers before a model repair loop can start. */
|
|
33053
|
+
function assertReferencedScriptsAreConfigured(name, scripts, ancestors) {
|
|
33054
|
+
if (ancestors.has(name))
|
|
33055
|
+
throw new CoderCheckSetupError(`scripts.${name} recursively calls the check pipeline.`);
|
|
33056
|
+
const command = scripts[name];
|
|
33057
|
+
if (typeof command !== 'string' || isCheckSetupRequired(command)) {
|
|
33058
|
+
throw new CoderCheckSetupError(`scripts.${name} is missing, empty, or contains a setup placeholder.`);
|
|
33059
|
+
}
|
|
33060
|
+
if (/^coder:(?:run|fix)$/u.test(name) || /\b(?:ptbk|promptbook)\s+coder\s+(?:run|fix)\b/u.test(command)) {
|
|
33061
|
+
throw new CoderCheckSetupError(`scripts.${name} calls Coder execution instead of project validation.`);
|
|
33062
|
+
}
|
|
33063
|
+
const nextAncestors = new Set([...ancestors, name]);
|
|
33064
|
+
// The shared inspector keeps root references before a directory change and leaves child workspaces opaque.
|
|
33065
|
+
for (const reference of projectScriptReferences(command)) {
|
|
33066
|
+
assertReferencedScriptsAreConfigured(reference, scripts, nextAncestors);
|
|
33067
|
+
}
|
|
33068
|
+
for (const prefix of ['pre', 'post']) {
|
|
33069
|
+
const lifecycleName = `${prefix}${name}`;
|
|
33070
|
+
if (scripts[lifecycleName] !== undefined)
|
|
33071
|
+
assertReferencedScriptsAreConfigured(lifecycleName, scripts, nextAncestors);
|
|
33072
|
+
}
|
|
33073
|
+
}
|
|
33074
|
+
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
32835
33075
|
|
|
32836
33076
|
/**
|
|
32837
|
-
* Runs the configured
|
|
33077
|
+
* Runs the configured check command inside the project root and returns its output.
|
|
32838
33078
|
*/
|
|
32839
|
-
async function
|
|
33079
|
+
async function runPromptCheckCommand(options) {
|
|
33080
|
+
await assertProjectCheckIsConfigured(options.command, options.projectPath);
|
|
32840
33081
|
const projectPath = toPosixPath(options.projectPath);
|
|
32841
33082
|
return await $runGoScriptWithOutput({
|
|
32842
33083
|
scriptPath: options.scriptPath,
|
|
33084
|
+
projectPath: options.projectPath,
|
|
32843
33085
|
scriptContent: spaceTrim(`
|
|
32844
|
-
cd
|
|
33086
|
+
cd ${quoteBashArgument(projectPath)} || exit 1
|
|
32845
33087
|
${options.command}
|
|
32846
33088
|
`),
|
|
32847
33089
|
logPath: options.logPath,
|
|
32848
33090
|
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
33091
|
+
signal: options.signal,
|
|
32849
33092
|
});
|
|
32850
33093
|
}
|
|
32851
33094
|
|
|
32852
33095
|
/**
|
|
32853
|
-
*
|
|
33096
|
+
* Shared constraints for initial repair PRDs and post-prompt check feedback.
|
|
33097
|
+
*/
|
|
33098
|
+
const CHECK_REPAIR_INSTRUCTIONS = _spaceTrim.spaceTrim(`
|
|
33099
|
+
Fix the underlying lint, typechecking, build, generated-code consistency, or test failure without weakening validation.
|
|
33100
|
+
Do not delete assertions, disable lint rules, remove failing checks from the aggregate, lower quality thresholds,
|
|
33101
|
+
skip a build, or force exit code zero merely to obtain a pass. Keep the project's chosen check scope intact.
|
|
33102
|
+
Missing or unconfigured validation requires project-owner setup; never replace it with a meaningless green result.
|
|
33103
|
+
`);
|
|
33104
|
+
|
|
33105
|
+
/**
|
|
33106
|
+
* Maximum number of coding attempts allowed for the same prompt when check keeps failing.
|
|
32854
33107
|
*/
|
|
32855
|
-
const
|
|
33108
|
+
const MAX_PROMPT_CHECK_ATTEMPTS = 3;
|
|
32856
33109
|
/**
|
|
32857
33110
|
* File extension used by generated shell scripts.
|
|
32858
33111
|
*/
|
|
@@ -32860,12 +33113,18 @@
|
|
|
32860
33113
|
/**
|
|
32861
33114
|
* Runs one coding prompt and, when configured, verifies it with a shell command that can feed failures back.
|
|
32862
33115
|
*/
|
|
32863
|
-
async function
|
|
32864
|
-
var _a, _b, _c, _d;
|
|
32865
|
-
|
|
33116
|
+
async function runPromptWithCheckFeedback(options) {
|
|
33117
|
+
var _a, _b, _c, _d, _e;
|
|
33118
|
+
(_a = options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
|
|
33119
|
+
const normalizedCheckCommand = (_b = options.checkCommand) === null || _b === void 0 ? void 0 : _b.trim();
|
|
33120
|
+
// Injected executors own their setup validation, just as they own command execution. The shared real executor
|
|
33121
|
+
// validates again after each agent attempt in case it changed the project's validation configuration.
|
|
33122
|
+
if (!options.runPromptCheckCommandExecutor) {
|
|
33123
|
+
await assertProjectCheckIsConfigured(normalizedCheckCommand, options.projectPath);
|
|
33124
|
+
}
|
|
32866
33125
|
const stepTracker = createCoderRunStepTracker(options.onStepStarted);
|
|
32867
|
-
if (!
|
|
32868
|
-
(
|
|
33126
|
+
if (!normalizedCheckCommand) {
|
|
33127
|
+
(_c = options.onAttemptStarted) === null || _c === void 0 ? void 0 : _c.call(options, 1);
|
|
32869
33128
|
await waitForPromptAttemptPauseCheckpoint(options.waitForPauseCheckpoint, options.runner.name, 1);
|
|
32870
33129
|
const result = await runRunnerPromptStep({
|
|
32871
33130
|
runOptions: options,
|
|
@@ -32875,10 +33134,10 @@
|
|
|
32875
33134
|
});
|
|
32876
33135
|
return { ...result, attemptCount: 1, steps: stepTracker.steps };
|
|
32877
33136
|
}
|
|
32878
|
-
const
|
|
33137
|
+
const runPromptCheckCommandExecutor = (_d = options.runPromptCheckCommandExecutor) !== null && _d !== void 0 ? _d : runPromptCheckCommand;
|
|
32879
33138
|
let promptForCurrentAttempt = options.prompt;
|
|
32880
|
-
for (let attemptCount = 1; attemptCount <=
|
|
32881
|
-
(
|
|
33139
|
+
for (let attemptCount = 1; attemptCount <= MAX_PROMPT_CHECK_ATTEMPTS; attemptCount++) {
|
|
33140
|
+
(_e = options.onAttemptStarted) === null || _e === void 0 ? void 0 : _e.call(options, attemptCount);
|
|
32882
33141
|
await waitForPromptAttemptPauseCheckpoint(options.waitForPauseCheckpoint, options.runner.name, attemptCount);
|
|
32883
33142
|
const result = await runRunnerPromptStep({
|
|
32884
33143
|
runOptions: options,
|
|
@@ -32886,42 +33145,44 @@
|
|
|
32886
33145
|
kind: attemptCount === 1 ? 'implementation' : 'fixing',
|
|
32887
33146
|
stepTracker,
|
|
32888
33147
|
});
|
|
32889
|
-
await
|
|
32890
|
-
console.info(colors__default["default"].gray(`Running
|
|
32891
|
-
const
|
|
32892
|
-
|
|
32893
|
-
|
|
33148
|
+
await waitForCheckPauseCheckpoint(options.waitForPauseCheckpoint, normalizedCheckCommand, attemptCount);
|
|
33149
|
+
console.info(colors__default["default"].gray(`Running check command after attempt #${attemptCount}: ${normalizedCheckCommand}`));
|
|
33150
|
+
const failedCheck = await runCheckStep({
|
|
33151
|
+
runPromptCheckCommandExecutor,
|
|
33152
|
+
checkCommand: normalizedCheckCommand,
|
|
32894
33153
|
runOptions: options,
|
|
32895
33154
|
stepTracker,
|
|
32896
33155
|
});
|
|
32897
|
-
if (
|
|
33156
|
+
if (failedCheck === undefined) {
|
|
32898
33157
|
return { ...result, attemptCount, steps: stepTracker.steps };
|
|
32899
33158
|
}
|
|
32900
|
-
const
|
|
32901
|
-
const
|
|
32902
|
-
if (attemptCount >=
|
|
32903
|
-
console.error(colors__default["default"].red(`
|
|
32904
|
-
throw new
|
|
33159
|
+
const fullCheckOutput = formatUnknownErrorDetails(failedCheck.error);
|
|
33160
|
+
const feedbackCheckOutput = limitCheckOutput(fullCheckOutput);
|
|
33161
|
+
if (attemptCount >= MAX_PROMPT_CHECK_ATTEMPTS) {
|
|
33162
|
+
console.error(colors__default["default"].red(`Check failed for ${options.promptLabel} after ${attemptCount} attempts.`));
|
|
33163
|
+
throw new NotAllowed(buildFinalCheckFailureMessage({
|
|
32905
33164
|
promptLabel: options.promptLabel,
|
|
32906
|
-
|
|
33165
|
+
checkCommand: normalizedCheckCommand,
|
|
32907
33166
|
attemptCount,
|
|
32908
|
-
|
|
33167
|
+
checkOutput: fullCheckOutput,
|
|
32909
33168
|
}));
|
|
32910
33169
|
}
|
|
32911
|
-
console.warn(colors__default["default"].yellow(`
|
|
32912
|
-
promptForCurrentAttempt = appendCoderContext(options.prompt,
|
|
32913
|
-
|
|
33170
|
+
console.warn(colors__default["default"].yellow(`Check failed for ${options.promptLabel} on attempt #${attemptCount}. Sending feedback to ${options.runner.name} and retrying...`));
|
|
33171
|
+
promptForCurrentAttempt = appendCoderContext(options.prompt, buildCheckFeedback({
|
|
33172
|
+
checkCommand: normalizedCheckCommand,
|
|
32914
33173
|
failedAttemptCount: attemptCount,
|
|
32915
|
-
|
|
33174
|
+
checkOutput: feedbackCheckOutput,
|
|
32916
33175
|
}));
|
|
32917
33176
|
}
|
|
32918
|
-
throw new
|
|
33177
|
+
throw new UnexpectedError('Unexpected prompt check state.');
|
|
32919
33178
|
}
|
|
32920
33179
|
/**
|
|
32921
33180
|
* Runs one coding attempt through the runner, timing it and recording it as an implementation or fixing step.
|
|
32922
33181
|
*/
|
|
32923
33182
|
async function runRunnerPromptStep(options) {
|
|
33183
|
+
var _a, _b;
|
|
32924
33184
|
const { runOptions, prompt, kind, stepTracker } = options;
|
|
33185
|
+
(_a = runOptions.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
|
|
32925
33186
|
await stepTracker.startStep(kind);
|
|
32926
33187
|
const stepStartedTimeMs = Date.now();
|
|
32927
33188
|
const result = await runOptions.runner.runPrompt({
|
|
@@ -32931,33 +33192,41 @@
|
|
|
32931
33192
|
logPath: runOptions.logPath,
|
|
32932
33193
|
preserveArtifactsOnSuccess: runOptions.preserveArtifactsOnSuccess,
|
|
32933
33194
|
waitForPauseCheckpoint: runOptions.waitForPauseCheckpoint,
|
|
33195
|
+
...(runOptions.signal ? { signal: runOptions.signal } : {}),
|
|
32934
33196
|
});
|
|
33197
|
+
(_b = runOptions.signal) === null || _b === void 0 ? void 0 : _b.throwIfAborted();
|
|
32935
33198
|
stepTracker.finishStep({ kind, usage: result.usage, durationMs: Date.now() - stepStartedTimeMs }, result.loginMethod);
|
|
32936
33199
|
return result;
|
|
32937
33200
|
}
|
|
32938
33201
|
/**
|
|
32939
|
-
* Runs the
|
|
32940
|
-
* returns the failure (or `undefined` when the
|
|
33202
|
+
* Runs the check command, timing it and recording it as a checking step regardless of the outcome, and
|
|
33203
|
+
* returns the failure (or `undefined` when the check passed).
|
|
32941
33204
|
*/
|
|
32942
|
-
async function
|
|
32943
|
-
|
|
32944
|
-
|
|
33205
|
+
async function runCheckStep(options) {
|
|
33206
|
+
var _a, _b, _c;
|
|
33207
|
+
const { runPromptCheckCommandExecutor, checkCommand, runOptions, stepTracker } = options;
|
|
33208
|
+
(_a = runOptions.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
|
|
33209
|
+
await stepTracker.startStep('checking');
|
|
32945
33210
|
const stepStartedTimeMs = Date.now();
|
|
32946
33211
|
try {
|
|
32947
|
-
await
|
|
32948
|
-
command:
|
|
33212
|
+
await runPromptCheckCommandExecutor({
|
|
33213
|
+
command: checkCommand,
|
|
32949
33214
|
projectPath: runOptions.projectPath,
|
|
32950
|
-
scriptPath:
|
|
33215
|
+
scriptPath: buildPromptCheckScriptPath(runOptions.scriptPath),
|
|
32951
33216
|
logPath: runOptions.logPath,
|
|
32952
33217
|
preserveArtifactsOnSuccess: runOptions.preserveArtifactsOnSuccess,
|
|
33218
|
+
...(runOptions.signal ? { signal: runOptions.signal } : {}),
|
|
32953
33219
|
});
|
|
33220
|
+
(_b = runOptions.signal) === null || _b === void 0 ? void 0 : _b.throwIfAborted();
|
|
32954
33221
|
return undefined;
|
|
32955
33222
|
}
|
|
32956
33223
|
catch (error) {
|
|
33224
|
+
if (error instanceof CoderCheckSetupError || ((_c = runOptions.signal) === null || _c === void 0 ? void 0 : _c.aborted))
|
|
33225
|
+
throw error;
|
|
32957
33226
|
return { error };
|
|
32958
33227
|
}
|
|
32959
33228
|
finally {
|
|
32960
|
-
stepTracker.finishStep({ kind: '
|
|
33229
|
+
stepTracker.finishStep({ kind: 'checking', usage: null, durationMs: Date.now() - stepStartedTimeMs });
|
|
32961
33230
|
}
|
|
32962
33231
|
}
|
|
32963
33232
|
/**
|
|
@@ -32971,13 +33240,13 @@
|
|
|
32971
33240
|
}));
|
|
32972
33241
|
}
|
|
32973
33242
|
/**
|
|
32974
|
-
* Waits for a pause checkpoint immediately before one
|
|
33243
|
+
* Waits for a pause checkpoint immediately before one check command begins.
|
|
32975
33244
|
*/
|
|
32976
|
-
async function
|
|
33245
|
+
async function waitForCheckPauseCheckpoint(waitForPauseCheckpoint, checkCommand, attemptCount) {
|
|
32977
33246
|
await (waitForPauseCheckpoint === null || waitForPauseCheckpoint === void 0 ? void 0 : waitForPauseCheckpoint({
|
|
32978
|
-
checkpointLabel:
|
|
33247
|
+
checkpointLabel: buildCheckPauseLabel(attemptCount),
|
|
32979
33248
|
phase: 'verifying',
|
|
32980
|
-
statusMessage: `Running
|
|
33249
|
+
statusMessage: `Running check after attempt #${attemptCount}: ${checkCommand}`,
|
|
32981
33250
|
}));
|
|
32982
33251
|
}
|
|
32983
33252
|
/**
|
|
@@ -32993,51 +33262,53 @@
|
|
|
32993
33262
|
return `Calling ${runnerName} (attempt ${attemptCount})`;
|
|
32994
33263
|
}
|
|
32995
33264
|
/**
|
|
32996
|
-
* Builds the human-readable pause label used before one
|
|
33265
|
+
* Builds the human-readable pause label used before one check command begins.
|
|
32997
33266
|
*/
|
|
32998
|
-
function
|
|
32999
|
-
return `running
|
|
33267
|
+
function buildCheckPauseLabel(attemptCount) {
|
|
33268
|
+
return `running check after attempt #${attemptCount}`;
|
|
33000
33269
|
}
|
|
33001
33270
|
/**
|
|
33002
|
-
* Builds one feedback block appended to the next coding attempt after
|
|
33271
|
+
* Builds one feedback block appended to the next coding attempt after checks fail.
|
|
33003
33272
|
*/
|
|
33004
|
-
function
|
|
33273
|
+
function buildCheckFeedback({ checkCommand, failedAttemptCount, checkOutput, }) {
|
|
33005
33274
|
const nextAttemptCount = failedAttemptCount + 1;
|
|
33006
33275
|
return spaceTrim((block) => `
|
|
33007
|
-
The previous implementation did not pass the required
|
|
33276
|
+
The previous implementation did not pass the required check command.
|
|
33008
33277
|
|
|
33009
|
-
## Automated
|
|
33010
|
-
- Retry attempt: ${nextAttemptCount} of ${
|
|
33011
|
-
-
|
|
33012
|
-
- Update the current implementation so the
|
|
33278
|
+
## Automated check feedback
|
|
33279
|
+
- Retry attempt: ${nextAttemptCount} of ${MAX_PROMPT_CHECK_ATTEMPTS}
|
|
33280
|
+
- Check command: \`${checkCommand}\`
|
|
33281
|
+
- Update the current implementation so the check command passes without breaking the original task requirements.
|
|
33013
33282
|
|
|
33014
|
-
|
|
33283
|
+
${block(CHECK_REPAIR_INSTRUCTIONS)}
|
|
33284
|
+
|
|
33285
|
+
### Check output
|
|
33015
33286
|
\`\`\`
|
|
33016
|
-
${block(
|
|
33287
|
+
${block(checkOutput)}
|
|
33017
33288
|
\`\`\`
|
|
33018
33289
|
`);
|
|
33019
33290
|
}
|
|
33020
33291
|
/**
|
|
33021
|
-
* Builds the final error message written when
|
|
33292
|
+
* Builds the final error message written when check still fails after all retries.
|
|
33022
33293
|
*/
|
|
33023
|
-
function
|
|
33294
|
+
function buildFinalCheckFailureMessage({ promptLabel, checkCommand, attemptCount, checkOutput, }) {
|
|
33024
33295
|
return spaceTrim((block) => `
|
|
33025
|
-
|
|
33296
|
+
Check command \`${checkCommand}\` failed for \`${promptLabel}\` after ${attemptCount} attempts.
|
|
33026
33297
|
|
|
33027
|
-
###
|
|
33298
|
+
### Check output
|
|
33028
33299
|
\`\`\`
|
|
33029
|
-
${block(
|
|
33300
|
+
${block(checkOutput)}
|
|
33030
33301
|
\`\`\`
|
|
33031
33302
|
`);
|
|
33032
33303
|
}
|
|
33033
33304
|
/**
|
|
33034
|
-
* Derives a dedicated temp-script path for
|
|
33305
|
+
* Derives a dedicated temp-script path for check commands.
|
|
33035
33306
|
*/
|
|
33036
|
-
function
|
|
33307
|
+
function buildPromptCheckScriptPath(scriptPath) {
|
|
33037
33308
|
if (scriptPath.toLowerCase().endsWith(SHELL_SCRIPT_EXTENSION)) {
|
|
33038
|
-
return `${scriptPath.slice(0, -SHELL_SCRIPT_EXTENSION.length)}.
|
|
33309
|
+
return `${scriptPath.slice(0, -SHELL_SCRIPT_EXTENSION.length)}.check.sh`;
|
|
33039
33310
|
}
|
|
33040
|
-
return `${scriptPath}.
|
|
33311
|
+
return `${scriptPath}.check.sh`;
|
|
33041
33312
|
}
|
|
33042
33313
|
|
|
33043
33314
|
/**
|
|
@@ -41937,16 +42208,16 @@
|
|
|
41937
42208
|
* Answers one queued `.book` message thread and moves it to `messages/finished`.
|
|
41938
42209
|
*/
|
|
41939
42210
|
async function tickAgentMessages(options, tickOptions = {}) {
|
|
41940
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
42211
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
41941
42212
|
validateAgentRunOptions(options);
|
|
41942
|
-
const projectPath = tickOptions.projectPath
|
|
42213
|
+
const projectPath = (_b = (_a = tickOptions.projectPath) !== null && _a !== void 0 ? _a : options.projectPath) !== null && _b !== void 0 ? _b : process.cwd();
|
|
41943
42214
|
let queueSnapshot = await loadAgentMessageQueueSnapshot(projectPath);
|
|
41944
42215
|
let queuedMessage = resolveSelectedQueuedMessage(queueSnapshot, tickOptions.queuedMessage);
|
|
41945
42216
|
if (!queuedMessage) {
|
|
41946
42217
|
announceNoQueuedMessages(tickOptions);
|
|
41947
42218
|
return { isMessageProcessed: false };
|
|
41948
42219
|
}
|
|
41949
|
-
if (tickOptions.uiHandle && !((
|
|
42220
|
+
if (tickOptions.uiHandle && !((_c = tickOptions.uiPresentation) === null || _c === void 0 ? void 0 : _c.isSharedDashboard)) {
|
|
41950
42221
|
updateAgentRunUiForPulling(tickOptions.uiHandle, queueSnapshot, 'Pulling latest changes before answering the next message');
|
|
41951
42222
|
}
|
|
41952
42223
|
const autoPullTimestamp = await pullLatestChangesForAgentQueueIfEnabled({
|
|
@@ -41958,7 +42229,7 @@
|
|
|
41958
42229
|
queueSnapshot = await loadAgentMessageQueueSnapshot(projectPath);
|
|
41959
42230
|
queuedMessage = resolveSelectedQueuedMessage(queueSnapshot, tickOptions.queuedMessage);
|
|
41960
42231
|
if (!queuedMessage) {
|
|
41961
|
-
if (tickOptions.uiHandle && !((
|
|
42232
|
+
if (tickOptions.uiHandle && !((_d = tickOptions.uiPresentation) === null || _d === void 0 ? void 0 : _d.isSharedDashboard)) {
|
|
41962
42233
|
updateAgentRunUiForWatching(tickOptions.uiHandle, queueSnapshot);
|
|
41963
42234
|
}
|
|
41964
42235
|
announceNoQueuedMessages(tickOptions);
|
|
@@ -41977,24 +42248,24 @@
|
|
|
41977
42248
|
actualRunnerModel,
|
|
41978
42249
|
queuedMessage,
|
|
41979
42250
|
uiHandle,
|
|
41980
|
-
isSharedDashboard: (
|
|
42251
|
+
isSharedDashboard: (_e = tickOptions.uiPresentation) === null || _e === void 0 ? void 0 : _e.isSharedDashboard,
|
|
41981
42252
|
});
|
|
41982
|
-
if (!((
|
|
41983
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.updateProgress(((
|
|
42253
|
+
if (!((_f = tickOptions.uiPresentation) === null || _f === void 0 ? void 0 : _f.isSharedDashboard)) {
|
|
42254
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.updateProgress(((_g = tickOptions.uiPresentation) === null || _g === void 0 ? void 0 : _g.completedProgressStats) ||
|
|
41984
42255
|
createAgentQueueProgressSnapshot({
|
|
41985
42256
|
finishedMessageCount: queueSnapshot.finishedMessageCount + 1,
|
|
41986
42257
|
queuedMessages: removeQueuedMessageFromSnapshot(queueSnapshot, queuedMessage),
|
|
41987
42258
|
}));
|
|
41988
|
-
if ((
|
|
42259
|
+
if ((_h = tickOptions.uiPresentation) === null || _h === void 0 ? void 0 : _h.completedAgentStatusLines) {
|
|
41989
42260
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAgentStatusLines([...tickOptions.uiPresentation.completedAgentStatusLines]);
|
|
41990
42261
|
}
|
|
41991
|
-
if ((
|
|
42262
|
+
if ((_j = tickOptions.uiPresentation) === null || _j === void 0 ? void 0 : _j.completedAgentStatusTableRows) {
|
|
41992
42263
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAgentStatusTableRows([...tickOptions.uiPresentation.completedAgentStatusTableRows]);
|
|
41993
42264
|
}
|
|
41994
|
-
if ((
|
|
42265
|
+
if ((_k = tickOptions.uiPresentation) === null || _k === void 0 ? void 0 : _k.completedMessagePreviewLines) {
|
|
41995
42266
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setMessagePreviewLines([...tickOptions.uiPresentation.completedMessagePreviewLines]);
|
|
41996
42267
|
}
|
|
41997
|
-
if ((
|
|
42268
|
+
if ((_l = tickOptions.uiPresentation) === null || _l === void 0 ? void 0 : _l.completedMessagePreviewSections) {
|
|
41998
42269
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setMessagePreviewSections([
|
|
41999
42270
|
...tickOptions.uiPresentation.completedMessagePreviewSections,
|
|
42000
42271
|
]);
|
|
@@ -42078,7 +42349,7 @@
|
|
|
42078
42349
|
try {
|
|
42079
42350
|
try {
|
|
42080
42351
|
promptRunResult = await withPromptRuntimeLog(scriptPath, async (logPath) => {
|
|
42081
|
-
const runResult = await
|
|
42352
|
+
const runResult = await runPromptWithCheckFeedback({
|
|
42082
42353
|
runner,
|
|
42083
42354
|
prompt,
|
|
42084
42355
|
scriptPath,
|
|
@@ -42505,12 +42776,12 @@
|
|
|
42505
42776
|
* Watches all direct child agent repositories from the current directory in one shared session.
|
|
42506
42777
|
*/
|
|
42507
42778
|
async function runMultipleAgentMessages(options, controls = {}) {
|
|
42508
|
-
var _a, _b;
|
|
42779
|
+
var _a, _b, _c;
|
|
42509
42780
|
validateAgentRunOptions(options);
|
|
42510
42781
|
validateAgentWatchOptions('ptbk agent-folder run-multiple', options);
|
|
42511
|
-
const rootPath = process.cwd();
|
|
42782
|
+
const rootPath = (_a = options.projectPath) !== null && _a !== void 0 ? _a : process.cwd();
|
|
42512
42783
|
const shouldContinue = controls.shouldContinue || (() => just(true));
|
|
42513
|
-
const queuePollIntervalMs = (
|
|
42784
|
+
const queuePollIntervalMs = (_b = controls.queuePollIntervalMs) !== null && _b !== void 0 ? _b : MULTI_AGENT_QUEUE_POLL_INTERVAL_MS;
|
|
42514
42785
|
const watchErrorLogDirectoryPath = controls.watchErrorLogDirectoryPath || rootPath;
|
|
42515
42786
|
const ignoreMatcher = createAgentIgnoreMatcher(options.ignorePatterns);
|
|
42516
42787
|
const githubSynchronizer = new MultipleAgentGithubSynchronizer();
|
|
@@ -42534,7 +42805,7 @@
|
|
|
42534
42805
|
watchErrorLogDirectoryPath,
|
|
42535
42806
|
});
|
|
42536
42807
|
isWatchSessionInitialized = true;
|
|
42537
|
-
(
|
|
42808
|
+
(_c = controls.onUiInitialized) === null || _c === void 0 ? void 0 : _c.call(controls, uiPresenter.uiHandle);
|
|
42538
42809
|
if (!uiPresenter.uiHandle) {
|
|
42539
42810
|
console.info(colors__default["default"].green('Watching direct child agent repositories for queued messages.'));
|
|
42540
42811
|
}
|
|
@@ -43793,6 +44064,7 @@
|
|
|
43793
44064
|
* @private internal registration helper for workspace CLI commands
|
|
43794
44065
|
*/
|
|
43795
44066
|
function addWorkspaceRepositoryOptions(command) {
|
|
44067
|
+
addProjectPathOption(command);
|
|
43796
44068
|
if (!command.options.some((option) => option.long === '--no-questions'))
|
|
43797
44069
|
addQuestionsOption(command);
|
|
43798
44070
|
command.addHelpText('after', `\n${WORKSPACE_REPOSITORY_DESCRIPTION}\n`);
|
|
@@ -43894,17 +44166,7 @@
|
|
|
43894
44166
|
* @private shared workspace discovery for CLI commands
|
|
43895
44167
|
*/
|
|
43896
44168
|
async function $resolveWorkspaceRepository(projectDirectory = process.cwd()) {
|
|
43897
|
-
const
|
|
43898
|
-
let projectPath;
|
|
43899
|
-
try {
|
|
43900
|
-
projectPath = await promises.realpath(requestedPath);
|
|
43901
|
-
if (!(await promises.stat(projectPath)).isDirectory()) {
|
|
43902
|
-
throw new EnvironmentMismatchError(`The project path \`${requestedPath}\` is not a directory.`);
|
|
43903
|
-
}
|
|
43904
|
-
}
|
|
43905
|
-
catch (error) {
|
|
43906
|
-
throw new EnvironmentMismatchError(_spaceTrim.spaceTrim(`Cannot access project directory \`${requestedPath}\`. Check that it exists and is accessible.\n\n${describeWorkspaceError(error)}`));
|
|
43907
|
-
}
|
|
44169
|
+
const projectPath = await resolveProjectDirectory(projectDirectory);
|
|
43908
44170
|
return $inspectWorkspaceRepository(projectPath);
|
|
43909
44171
|
}
|
|
43910
44172
|
/**
|
|
@@ -44016,7 +44278,7 @@
|
|
|
44016
44278
|
// Git may skip damaged inner metadata and find a valid parent. Do not silently use that parent
|
|
44017
44279
|
// for a project whose own checkout needs repair.
|
|
44018
44280
|
await $assertNoBrokenRepositoryMetadata(projectPath, repositoryRoot);
|
|
44019
|
-
const gitDirectory = (await $runWorkspaceGit(projectPath, ['rev-parse', '--absolute-git-dir'])).trim();
|
|
44281
|
+
const gitDirectory = await promises.realpath((await $runWorkspaceGit(projectPath, ['rev-parse', '--absolute-git-dir'])).trim());
|
|
44020
44282
|
// Also validate the index and metadata, without refreshing the index or depending on an existing commit.
|
|
44021
44283
|
await $runWorkspaceGit(projectPath, ['status', '--porcelain', '--untracked-files=no']);
|
|
44022
44284
|
return { projectPath, repositoryRoot, gitDirectory, repositoryStatus: 'reused' };
|
|
@@ -44344,10 +44606,15 @@
|
|
|
44344
44606
|
addQuestionsOption(command);
|
|
44345
44607
|
addWorkspaceRepositoryOptions(command);
|
|
44346
44608
|
command.action(handleActionErrors(async (descriptionArgument, cliOptions) => {
|
|
44609
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
44347
44610
|
const { priority, template: templateOption } = cliOptions;
|
|
44348
44611
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
44349
44612
|
const questionsOptions = normalizeQuestionsCliOptions(cliOptions);
|
|
44350
|
-
const workspace = await $preflightWorkspaceRepository({
|
|
44613
|
+
const workspace = await $preflightWorkspaceRepository({
|
|
44614
|
+
...projectOptions,
|
|
44615
|
+
policy: 'mutate',
|
|
44616
|
+
...questionsOptions,
|
|
44617
|
+
});
|
|
44351
44618
|
const { projectPath } = workspace;
|
|
44352
44619
|
const description = await resolveCoderPromptDescription(descriptionArgument, questionsOptions);
|
|
44353
44620
|
// Note: Import the git synchronization dynamically to keep the CLI fast for runs without `--commit`
|
|
@@ -44570,7 +44837,9 @@
|
|
|
44570
44837
|
`));
|
|
44571
44838
|
addWorkspaceRepositoryOptions(command);
|
|
44572
44839
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
44840
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
44573
44841
|
const workspace = await $preflightWorkspaceRepository({
|
|
44842
|
+
...projectOptions,
|
|
44574
44843
|
policy: 'read-only',
|
|
44575
44844
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
44576
44845
|
});
|
|
@@ -44811,8 +45080,10 @@
|
|
|
44811
45080
|
command.option('--limit <candidate-count>', 'Create at most this many refactor prompts, keeping the most important candidates', createPositiveIntegerOptionParser('--limit'));
|
|
44812
45081
|
addWorkspaceRepositoryOptions(command);
|
|
44813
45082
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
45083
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
44814
45084
|
const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL, limit } = cliOptions;
|
|
44815
45085
|
const workspace = await $preflightWorkspaceRepository({
|
|
45086
|
+
...projectOptions,
|
|
44816
45087
|
policy: 'mutate',
|
|
44817
45088
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
44818
45089
|
});
|
|
@@ -44846,8 +45117,10 @@
|
|
|
44846
45117
|
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
|
|
44847
45118
|
addWorkspaceRepositoryOptions(command);
|
|
44848
45119
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
45120
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
44849
45121
|
const { priority = 0 } = cliOptions;
|
|
44850
45122
|
const workspace = await $preflightWorkspaceRepository({
|
|
45123
|
+
...projectOptions,
|
|
44851
45124
|
policy: 'read-only',
|
|
44852
45125
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
44853
45126
|
});
|
|
@@ -45001,10 +45274,12 @@
|
|
|
45001
45274
|
addCoderGitSyncOptions(command);
|
|
45002
45275
|
addWorkspaceRepositoryOptions(command);
|
|
45003
45276
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
45277
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
45004
45278
|
const { count: countOption, template: templateOption } = cliOptions;
|
|
45005
45279
|
const boilerplateCount = parseBoilerplateCount(countOption);
|
|
45006
45280
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
45007
45281
|
const workspace = await $preflightWorkspaceRepository({
|
|
45282
|
+
...projectOptions,
|
|
45008
45283
|
policy: 'mutate',
|
|
45009
45284
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
45010
45285
|
});
|
|
@@ -46043,16 +46318,16 @@
|
|
|
46043
46318
|
...getDefaultCoderProjectPromptTemplateDefinitions().map(createCoderPromptTemplateArtifactDefinition),
|
|
46044
46319
|
];
|
|
46045
46320
|
/**
|
|
46046
|
-
* Initializes artifacts referenced by freshly added scripts.
|
|
46321
|
+
* Initializes essential context and artifacts referenced by freshly added scripts. Books are ensured separately.
|
|
46047
46322
|
*
|
|
46048
|
-
*
|
|
46323
|
+
* AGENTS.md is essential even when every script already exists or uses implicit defaults.
|
|
46049
46324
|
*
|
|
46050
46325
|
* @private function of `initializeCoderProjectConfiguration`
|
|
46051
46326
|
*/
|
|
46052
46327
|
async function ensureCoderReferencedArtifacts(projectPath, referencedArtifactPaths) {
|
|
46053
46328
|
const ensuredArtifacts = [];
|
|
46054
46329
|
for (const { relativeFilePath, ensureArtifactFile } of CODER_REFERENCED_ARTIFACT_DEFINITIONS) {
|
|
46055
|
-
if (!referencedArtifactPaths.has(relativeFilePath)) {
|
|
46330
|
+
if (relativeFilePath !== AGENTS_FILE_PATH && !referencedArtifactPaths.has(relativeFilePath)) {
|
|
46056
46331
|
ensuredArtifacts.push({ relativeFilePath, status: 'not-referenced' });
|
|
46057
46332
|
continue;
|
|
46058
46333
|
}
|
|
@@ -46671,7 +46946,7 @@
|
|
|
46671
46946
|
/**
|
|
46672
46947
|
* Name of the npm script which `ptbk coder run` uses to verify the project.
|
|
46673
46948
|
*/
|
|
46674
|
-
const
|
|
46949
|
+
const CHECK_SCRIPT_NAME = 'check';
|
|
46675
46950
|
/**
|
|
46676
46951
|
* Default npm scripts initialized by `ptbk coder init`.
|
|
46677
46952
|
*
|
|
@@ -46691,14 +46966,13 @@
|
|
|
46691
46966
|
{
|
|
46692
46967
|
scriptName: 'coder:plan',
|
|
46693
46968
|
scriptCommand: 'npx ptbk coder plan --harness openai-codex',
|
|
46694
|
-
referencedArtifactPaths: [
|
|
46969
|
+
referencedArtifactPaths: [CODER_DEVELOPER_AGENT_FILE_PATH, AGENTS_FILE_PATH, COMMON_PROMPT_TEMPLATE_FILE_PATH],
|
|
46695
46970
|
},
|
|
46696
46971
|
{
|
|
46697
46972
|
scriptName: 'coder:run',
|
|
46698
46973
|
scriptCommand: [
|
|
46699
46974
|
'npx ptbk coder run --harness openai-codex --thinking-level max',
|
|
46700
|
-
`--
|
|
46701
|
-
`--test "npm run ${CODER_TEST_SCRIPT_NAME}" --test-before yes-and-fix`,
|
|
46975
|
+
`--check "npm run ${CHECK_SCRIPT_NAME}" --check-before yes-and-fix`,
|
|
46702
46976
|
].join(' '),
|
|
46703
46977
|
referencedArtifactPaths: [CODER_DEVELOPER_AGENT_FILE_PATH, AGENTS_FILE_PATH],
|
|
46704
46978
|
},
|
|
@@ -46711,8 +46985,8 @@
|
|
|
46711
46985
|
{
|
|
46712
46986
|
// Note: The verification command of `coder:run` is a project-owned script, so every project can decide
|
|
46713
46987
|
// what "verified" means without touching the `coder:run` script itself
|
|
46714
|
-
scriptName:
|
|
46715
|
-
scriptCommand:
|
|
46988
|
+
scriptName: CHECK_SCRIPT_NAME,
|
|
46989
|
+
scriptCommand: CHECK_SETUP_PLACEHOLDER_COMMAND,
|
|
46716
46990
|
referencedArtifactPaths: [],
|
|
46717
46991
|
},
|
|
46718
46992
|
];
|
|
@@ -46777,12 +47051,13 @@
|
|
|
46777
47051
|
/**
|
|
46778
47052
|
* Ensures one JSON object field contains the provided string-record entries.
|
|
46779
47053
|
*
|
|
46780
|
-
* Entries
|
|
46781
|
-
*
|
|
47054
|
+
* Entries are additive unless a caller explicitly supplies a scoped migration callback.
|
|
47055
|
+
* Hand-tuned scripts and settings survive repeated `ptbk coder init`; migrations recognize generated entries only.
|
|
46782
47056
|
*
|
|
46783
47057
|
* @private function of `initializeCoderProjectConfiguration`
|
|
46784
47058
|
*/
|
|
46785
|
-
async function mergeStringRecordJsonFile({ projectPath, relativeFilePath, fieldPath, nextEntries, ensureParentDirectoryPath, }) {
|
|
47059
|
+
async function mergeStringRecordJsonFile({ projectPath, relativeFilePath, fieldPath, nextEntries, ensureParentDirectoryPath, transformExistingEntries, }) {
|
|
47060
|
+
var _a;
|
|
46786
47061
|
if (ensureParentDirectoryPath) {
|
|
46787
47062
|
await promises.mkdir(path.join(projectPath, ensureParentDirectoryPath), { recursive: true });
|
|
46788
47063
|
}
|
|
@@ -46792,7 +47067,7 @@
|
|
|
46792
47067
|
const jsonObject = fileContent === undefined ? {} : await parseJsonObjectFile(relativeFilePath, fileContent);
|
|
46793
47068
|
const existingEntries = getStringRecordOrDefault(jsonObject[fieldPath], relativeFilePath, fieldPath);
|
|
46794
47069
|
const addedEntryKeys = [];
|
|
46795
|
-
const mergedEntries = { ...existingEntries };
|
|
47070
|
+
const mergedEntries = { ...((_a = (await (transformExistingEntries === null || transformExistingEntries === void 0 ? void 0 : transformExistingEntries(existingEntries)))) !== null && _a !== void 0 ? _a : existingEntries) };
|
|
46796
47071
|
for (const [entryKey, entryValue] of Object.entries(nextEntries)) {
|
|
46797
47072
|
if (Object.prototype.hasOwnProperty.call(mergedEntries, entryKey)) {
|
|
46798
47073
|
// Note: The project already defines this entry, keep its own value untouched
|
|
@@ -46801,7 +47076,12 @@
|
|
|
46801
47076
|
mergedEntries[entryKey] = entryValue;
|
|
46802
47077
|
addedEntryKeys.push(entryKey);
|
|
46803
47078
|
}
|
|
46804
|
-
const
|
|
47079
|
+
for (const entryKey of Object.keys(mergedEntries)) {
|
|
47080
|
+
if (!Object.prototype.hasOwnProperty.call(existingEntries, entryKey) && !addedEntryKeys.includes(entryKey)) {
|
|
47081
|
+
addedEntryKeys.push(entryKey);
|
|
47082
|
+
}
|
|
47083
|
+
}
|
|
47084
|
+
const hasChanges = fileContent === undefined || JSON.stringify(mergedEntries) !== JSON.stringify(existingEntries);
|
|
46805
47085
|
if (!hasChanges) {
|
|
46806
47086
|
return { status: 'unchanged', addedEntryKeys };
|
|
46807
47087
|
}
|
|
@@ -46890,6 +47170,301 @@
|
|
|
46890
47170
|
}
|
|
46891
47171
|
// Note: [🟡] Code for coder init JSON merging [mergeStringRecordJsonFile](src/cli/cli-commands/coder/mergeStringRecordJsonFile.ts) should never be published outside of `@promptbook/cli`
|
|
46892
47172
|
|
|
47173
|
+
/** Old initialized aggregate entries, used only at this migration boundary. */
|
|
47174
|
+
const LEGACY_CHECK_SCRIPT_NAMES = ['test-for-ptbk-coder', 'check-for-ptbk-coder'];
|
|
47175
|
+
/** Conventional project validation scripts, ordered from lightweight checks to tests. */
|
|
47176
|
+
const VALIDATION_SCRIPT_GROUPS = [
|
|
47177
|
+
['lint', 'test-lint'],
|
|
47178
|
+
['typecheck', 'type-check', 'type-checking', 'check-types', 'test-types'],
|
|
47179
|
+
['build', 'test-build'],
|
|
47180
|
+
];
|
|
47181
|
+
/** Conventional leaf test families used when the project has no usable test aggregate. */
|
|
47182
|
+
const TEST_SCRIPT_GROUPS = [
|
|
47183
|
+
['test-unit', 'test:unit'],
|
|
47184
|
+
['test-integration', 'test:integration'],
|
|
47185
|
+
['test-e2e', 'test:e2e'],
|
|
47186
|
+
];
|
|
47187
|
+
/** Script names that must never be reached by a generated aggregate. */
|
|
47188
|
+
const NON_VALIDATION_SCRIPT_PATTERN = /^(?:check$|coder:|(?:dev|start|serve|watch|deploy|publish|install|preinstall|postinstall|prepare|reset|clean)(?:$|[:-]))/iu;
|
|
47189
|
+
/** Clearly unsuitable shell bodies are excluded even under a conventional validation name. */
|
|
47190
|
+
const UNSUITABLE_VALIDATION_BODY_PATTERN = /(?:\b(?:ptbk|promptbook)\s+coder\s+(?:run|fix)|\bcoder:(?:run|fix)\b|--watch(?:All)?(?:\b|=)|\b(?:watch|nodemon|concurrently|serve|deploy|publish|install|reset|rm|rmdir|del|remove-item)\b|--if-present|\|\||(?:^|[^&])&(?:$|[^&])|;|\bexit\s+0\b)/iu;
|
|
47191
|
+
/** Npm lifecycle hooks that run implicitly before and after a selected project script. */
|
|
47192
|
+
const SCRIPT_LIFECYCLE_PREFIXES = ['pre', 'post'];
|
|
47193
|
+
/**
|
|
47194
|
+
* Preserves project scripts, creates one canonical check, and migrates only exact generated caller forms.
|
|
47195
|
+
* @private shared package-script preparation for Coder initialization
|
|
47196
|
+
*/
|
|
47197
|
+
function prepareCoderPackageJsonScripts(existing, externalCallers = {}) {
|
|
47198
|
+
var _a;
|
|
47199
|
+
const scripts = { ...existing };
|
|
47200
|
+
const migrationInstructions = [];
|
|
47201
|
+
const legacyNames = LEGACY_CHECK_SCRIPT_NAMES.filter((name) => Object.prototype.hasOwnProperty.call(existing, name));
|
|
47202
|
+
let checkScriptSummary;
|
|
47203
|
+
if (Object.prototype.hasOwnProperty.call(existing, 'check')) {
|
|
47204
|
+
checkScriptSummary = 'Preserved project scripts.check exactly; Coder executes npm run check.';
|
|
47205
|
+
}
|
|
47206
|
+
else if (legacyNames.length > 0) {
|
|
47207
|
+
const sourceName = legacyNames[0];
|
|
47208
|
+
const isRecursive = scriptReaches(sourceName, 'check', existing, new Set()) ||
|
|
47209
|
+
scriptReaches(sourceName, sourceName, existing, new Set()) ||
|
|
47210
|
+
scriptReaches(sourceName, 'coder:run', existing, new Set()) ||
|
|
47211
|
+
scriptReaches(sourceName, 'coder:fix', existing, new Set());
|
|
47212
|
+
const conflictingLifecycleNames = SCRIPT_LIFECYCLE_PREFIXES.filter((prefix) => existing[`${prefix}check`] !== undefined &&
|
|
47213
|
+
existing[`${prefix}${sourceName}`] !== existing[`${prefix}check`]).map((prefix) => `${prefix}check`);
|
|
47214
|
+
scripts.check =
|
|
47215
|
+
isRecursive || conflictingLifecycleNames.length > 0
|
|
47216
|
+
? CHECK_SETUP_PLACEHOLDER_COMMAND
|
|
47217
|
+
: existing[sourceName];
|
|
47218
|
+
if (!isRecursive && conflictingLifecycleNames.length === 0) {
|
|
47219
|
+
// npm runs these hooks implicitly. Preserve their bodies as well as the main script's scope.
|
|
47220
|
+
for (const prefix of SCRIPT_LIFECYCLE_PREFIXES) {
|
|
47221
|
+
const legacyHook = existing[`${prefix}${sourceName}`];
|
|
47222
|
+
if (legacyHook !== undefined)
|
|
47223
|
+
scripts[`${prefix}check`] = legacyHook;
|
|
47224
|
+
}
|
|
47225
|
+
}
|
|
47226
|
+
checkScriptSummary = isRecursive
|
|
47227
|
+
? `Kept recursive scripts.${sourceName} unchanged; configure scripts.check with validation that does not call check or Coder recursively.`
|
|
47228
|
+
: conflictingLifecycleNames.length > 0
|
|
47229
|
+
? `Kept scripts.${sourceName} and conflicting ${conflictingLifecycleNames.join(', ')} hooks unchanged; configure scripts.check and its lifecycle hooks to preserve the required validation.`
|
|
47230
|
+
: `Preserved scripts.${sourceName}'s validation command and npm lifecycle hooks in scripts.check: ${scripts.check}`;
|
|
47231
|
+
}
|
|
47232
|
+
else {
|
|
47233
|
+
const selectedScripts = selectValidationScripts(existing);
|
|
47234
|
+
scripts.check =
|
|
47235
|
+
selectedScripts.length > 0
|
|
47236
|
+
? selectedScripts.map((name) => (name === 'test' ? 'npm test' : `npm run ${name}`)).join(' && ')
|
|
47237
|
+
: CHECK_SETUP_PLACEHOLDER_COMMAND;
|
|
47238
|
+
checkScriptSummary =
|
|
47239
|
+
selectedScripts.length > 0
|
|
47240
|
+
? `Generated scripts.check from the available validation scripts (${selectedScripts.join(', ')}): ${scripts.check}`
|
|
47241
|
+
: 'No usable validation scripts found. scripts.check contains a failing setup placeholder; configure it before running Coder.';
|
|
47242
|
+
}
|
|
47243
|
+
for (const [name, command] of Object.entries(existing)) {
|
|
47244
|
+
if (['check', ...legacyNames].some((verificationName) => name === verificationName ||
|
|
47245
|
+
SCRIPT_LIFECYCLE_PREFIXES.some((prefix) => name === `${prefix}${verificationName}`)))
|
|
47246
|
+
continue;
|
|
47247
|
+
const migratedCaller = migrateGeneratedCoderRunScript(command);
|
|
47248
|
+
if (migratedCaller !== undefined) {
|
|
47249
|
+
// A different existing check is authoritative, but changing a custom legacy caller's scope is not safe.
|
|
47250
|
+
const referencedLegacyName = legacyNames.find((legacyName) => command.includes(legacyName));
|
|
47251
|
+
const isConflictingCustomCheck = referencedLegacyName !== undefined &&
|
|
47252
|
+
!isLegacyCheckScopePreserved(referencedLegacyName, scripts) &&
|
|
47253
|
+
!isUnchangedLegacyCheckDefault(referencedLegacyName, scripts);
|
|
47254
|
+
if (!isConflictingCustomCheck)
|
|
47255
|
+
scripts[name] = migratedCaller;
|
|
47256
|
+
}
|
|
47257
|
+
}
|
|
47258
|
+
for (const legacyName of legacyNames) {
|
|
47259
|
+
const callers = Object.entries(scripts)
|
|
47260
|
+
.filter(([name, command]) => name !== legacyName && command.includes(legacyName))
|
|
47261
|
+
.map(([name]) => name);
|
|
47262
|
+
const isPreservedScope = isLegacyCheckScopePreserved(legacyName, scripts);
|
|
47263
|
+
const isObsoleteGeneratedDefault = isUnchangedLegacyCheckDefault(legacyName, scripts) && !isCheckSetupRequired(scripts.check);
|
|
47264
|
+
const files = (_a = externalCallers[legacyName]) !== null && _a !== void 0 ? _a : [];
|
|
47265
|
+
if (callers.length === 0 && files.length === 0 && (isPreservedScope || isObsoleteGeneratedDefault)) {
|
|
47266
|
+
delete scripts[legacyName];
|
|
47267
|
+
for (const prefix of SCRIPT_LIFECYCLE_PREFIXES)
|
|
47268
|
+
delete scripts[`${prefix}${legacyName}`];
|
|
47269
|
+
}
|
|
47270
|
+
else {
|
|
47271
|
+
migrationInstructions.push(`Kept scripts.${legacyName}${callers.length ? `; referenced by scripts.${callers.join(', scripts.')}` : ''}${files.length ? `; referenced by ${files.join(', ')}` : ''}${!isPreservedScope && !isObsoleteGeneratedDefault
|
|
47272
|
+
? '; its custom command or npm lifecycle hooks differ from scripts.check'
|
|
47273
|
+
: ''}. Preserve its required validation and pre/post hooks in scripts.check, update those callers to npm run check, then remove scripts.${legacyName} and its unused lifecycle hooks.`);
|
|
47274
|
+
}
|
|
47275
|
+
}
|
|
47276
|
+
for (const [name, command] of Object.entries(scripts)) {
|
|
47277
|
+
if (/\b(?:ptbk|promptbook)\s+coder\s+(?:run|server)\b|\brun-codex-prompts\b/u.test(command) &&
|
|
47278
|
+
/--test(?:-before)?(?:\s|=|$)/u.test(command)) {
|
|
47279
|
+
migrationInstructions.push(`Update scripts.${name}: replace --test with --check and --test-before with --check-before; review its shell expression manually. Existing command was preserved: ${command}`);
|
|
47280
|
+
}
|
|
47281
|
+
}
|
|
47282
|
+
let isCheckConfigured = true;
|
|
47283
|
+
try {
|
|
47284
|
+
assertProjectCheckScriptsAreConfigured(scripts);
|
|
47285
|
+
}
|
|
47286
|
+
catch (error) {
|
|
47287
|
+
if (!(error instanceof CoderCheckSetupError))
|
|
47288
|
+
throw error;
|
|
47289
|
+
isCheckConfigured = false;
|
|
47290
|
+
checkScriptSummary += ` Additional setup required: ${error.message}`;
|
|
47291
|
+
}
|
|
47292
|
+
return {
|
|
47293
|
+
scripts,
|
|
47294
|
+
checkScriptSummary,
|
|
47295
|
+
migrationInstructions,
|
|
47296
|
+
isCheckConfigured,
|
|
47297
|
+
};
|
|
47298
|
+
}
|
|
47299
|
+
/** Determines whether both the legacy command and its implicit npm validation hooks have been preserved. */
|
|
47300
|
+
function isLegacyCheckScopePreserved(name, scripts) {
|
|
47301
|
+
return (scripts[name] === scripts.check &&
|
|
47302
|
+
SCRIPT_LIFECYCLE_PREFIXES.every((prefix) => scripts[`${prefix}${name}`] === scripts[`${prefix}check`]));
|
|
47303
|
+
}
|
|
47304
|
+
/** Recognizes the generated default only when no custom lifecycle hooks extend its validation scope. */
|
|
47305
|
+
function isUnchangedLegacyCheckDefault(name, scripts) {
|
|
47306
|
+
return (scripts[name] === 'npm test' &&
|
|
47307
|
+
SCRIPT_LIFECYCLE_PREFIXES.every((prefix) => scripts[`${prefix}${name}`] === undefined));
|
|
47308
|
+
}
|
|
47309
|
+
/**
|
|
47310
|
+
* Recognizes unchanged generated run scripts, including the previous explicit Developer/context defaults.
|
|
47311
|
+
* Unknown shell expressions and custom harness configuration are preserved for manual migration.
|
|
47312
|
+
*/
|
|
47313
|
+
function migrateGeneratedCoderRunScript(command) {
|
|
47314
|
+
const prefix = 'npx ptbk coder run --harness openai-codex --thinking-level max';
|
|
47315
|
+
const defaultArguments = ['', ' --agent agents/developer.book --context AGENTS.md'];
|
|
47316
|
+
const verificationArguments = [
|
|
47317
|
+
' --test-before yes-and-fix',
|
|
47318
|
+
...LEGACY_CHECK_SCRIPT_NAMES.map((name) => ` --test "npm run ${name}" --test-before yes-and-fix`),
|
|
47319
|
+
...LEGACY_CHECK_SCRIPT_NAMES.map((name) => ` --check "npm run ${name}" --check-before yes-and-fix`),
|
|
47320
|
+
];
|
|
47321
|
+
const isGenerated = defaultArguments.some((defaults) => verificationArguments.some((verification) => command === prefix + defaults + verification));
|
|
47322
|
+
return isGenerated ? getDefaultCoderPackageJsonScripts()['coder:run'] : undefined;
|
|
47323
|
+
}
|
|
47324
|
+
/** Selects safe conventional scripts, avoiding duplicates already reached by another selected aggregate. */
|
|
47325
|
+
function selectValidationScripts(scripts) {
|
|
47326
|
+
if (SCRIPT_LIFECYCLE_PREFIXES.some((prefix) => scripts[`${prefix}check`] !== undefined &&
|
|
47327
|
+
!isUsableValidationScript(`${prefix}check`, scripts, new Set())))
|
|
47328
|
+
return [];
|
|
47329
|
+
const selected = [];
|
|
47330
|
+
for (const group of VALIDATION_SCRIPT_GROUPS) {
|
|
47331
|
+
const name = group.find((candidate) => isUsableValidationScript(candidate, scripts, new Set()));
|
|
47332
|
+
if (name !== undefined)
|
|
47333
|
+
selected.push(name);
|
|
47334
|
+
}
|
|
47335
|
+
if (isUsableValidationScript('test', scripts, new Set()))
|
|
47336
|
+
selected.push('test');
|
|
47337
|
+
else
|
|
47338
|
+
for (const group of TEST_SCRIPT_GROUPS) {
|
|
47339
|
+
const name = group.find((candidate) => isUsableValidationScript(candidate, scripts, new Set()));
|
|
47340
|
+
if (name !== undefined)
|
|
47341
|
+
selected.push(name);
|
|
47342
|
+
}
|
|
47343
|
+
return selected.filter((name) => !selected.some((other) => other !== name && scriptReaches(other, name, scripts, new Set())));
|
|
47344
|
+
}
|
|
47345
|
+
/** Inspects each body, referenced script, and implicit lifecycle hook before including it in an aggregate. */
|
|
47346
|
+
function isUsableValidationScript(name, scripts, visited) {
|
|
47347
|
+
const command = scripts[name];
|
|
47348
|
+
if (!command ||
|
|
47349
|
+
visited.has(name) ||
|
|
47350
|
+
NON_VALIDATION_SCRIPT_PATTERN.test(name) ||
|
|
47351
|
+
isCheckSetupRequired(command) ||
|
|
47352
|
+
UNSUITABLE_VALIDATION_BODY_PATTERN.test(command))
|
|
47353
|
+
return false;
|
|
47354
|
+
if (command.split('&&').every((part) => /^\s*(?:echo|printf|true|:)(?:\s|$)/iu.test(part)) ||
|
|
47355
|
+
/\bprocess\.exit\(\s*0\s*\)/u.test(command))
|
|
47356
|
+
return false;
|
|
47357
|
+
if (/\b(?:vite|next|astro|webpack-dev-server)\s+(?:dev|start|serve)\b/iu.test(command) ||
|
|
47358
|
+
/(?:^|&&)\s*(?:vite|webpack-dev-server)(?:\s*$|\s+--)/iu.test(command) ||
|
|
47359
|
+
(/\bvitest\b/iu.test(command) && !/\bvitest\s+run\b/iu.test(command)))
|
|
47360
|
+
return false;
|
|
47361
|
+
const nextVisited = new Set([...visited, name]);
|
|
47362
|
+
const references = projectScriptReferences(command);
|
|
47363
|
+
// Ambiguous package-manager flags and cwd switches cannot be composed confidently as root validation.
|
|
47364
|
+
if (/\b(?:npm|pnpm|yarn)\s+(?:--|run(?:-script)?\s+--)/u.test(command) ||
|
|
47365
|
+
(/\b(?:npm|pnpm|yarn)\b/u.test(command) && references.length === 0))
|
|
47366
|
+
return false;
|
|
47367
|
+
if (references.some((reference) => !isUsableValidationScript(reference, scripts, nextVisited)))
|
|
47368
|
+
return false;
|
|
47369
|
+
return SCRIPT_LIFECYCLE_PREFIXES.every((prefix) => {
|
|
47370
|
+
const lifecycleName = `${prefix}${name}`;
|
|
47371
|
+
return scripts[lifecycleName] === undefined || isUsableValidationScript(lifecycleName, scripts, nextVisited);
|
|
47372
|
+
});
|
|
47373
|
+
}
|
|
47374
|
+
/** Checks whether a selected aggregate already reaches another selected script. */
|
|
47375
|
+
function scriptReaches(name, target, scripts, visited) {
|
|
47376
|
+
var _a;
|
|
47377
|
+
if (visited.has(name))
|
|
47378
|
+
return false;
|
|
47379
|
+
const nextVisited = new Set([...visited, name]);
|
|
47380
|
+
const command = (_a = scripts[name]) !== null && _a !== void 0 ? _a : '';
|
|
47381
|
+
if ((target === 'coder:run' && /\b(?:ptbk|promptbook)\s+coder\s+run\b/u.test(command)) ||
|
|
47382
|
+
(target === 'coder:fix' && /\b(?:ptbk|promptbook)\s+coder\s+fix\b/u.test(command)))
|
|
47383
|
+
return true;
|
|
47384
|
+
const references = [
|
|
47385
|
+
...projectScriptReferences(command),
|
|
47386
|
+
...SCRIPT_LIFECYCLE_PREFIXES.map((prefix) => `${prefix}${name}`).filter((lifecycleName) => scripts[lifecycleName] !== undefined),
|
|
47387
|
+
];
|
|
47388
|
+
return references.some((reference) => reference === target || scriptReaches(reference, target, scripts, nextVisited));
|
|
47389
|
+
}
|
|
47390
|
+
|
|
47391
|
+
// cspell:ignore Procfile
|
|
47392
|
+
/** Runtime/dependency/history directories do not contain maintained project callers. */
|
|
47393
|
+
const IGNORED_CALLER_DIRECTORIES = new Set([
|
|
47394
|
+
'node_modules',
|
|
47395
|
+
'.git',
|
|
47396
|
+
'.promptbook',
|
|
47397
|
+
'.next',
|
|
47398
|
+
'.tmp',
|
|
47399
|
+
'dist',
|
|
47400
|
+
'build',
|
|
47401
|
+
'coverage',
|
|
47402
|
+
]);
|
|
47403
|
+
/** Only Coder's known task-history paths are excluded; the same names elsewhere can hold active callers. */
|
|
47404
|
+
const IGNORED_CALLER_HISTORY_PATHS = new Set(['prompts/done', 'prompts/traces']);
|
|
47405
|
+
/** Source and workflow files whose references must be preserved during npm script migration. */
|
|
47406
|
+
const CALLER_FILE_PATTERN = /\.(?:[cm]?jsx?|tsx?|json|ya?ml|md|sh|bash|ps1|cmd|bat|py|toml|xml|groovy)$/iu;
|
|
47407
|
+
/** Conventional workflow files which have no filename extension. */
|
|
47408
|
+
const CALLER_FILE_NAMES = new Set(['Makefile', 'Dockerfile', 'Jenkinsfile', 'Procfile']);
|
|
47409
|
+
/**
|
|
47410
|
+
* Finds external project callers conservatively; it never rewrites their shell expressions.
|
|
47411
|
+
* @private migration safety check for the Coder initializer
|
|
47412
|
+
*/
|
|
47413
|
+
async function findLegacyCoderCheckCallers(projectPath, legacyNames) {
|
|
47414
|
+
const callers = Object.fromEntries(legacyNames.map((name) => [name, []]));
|
|
47415
|
+
if (legacyNames.length === 0)
|
|
47416
|
+
return callers;
|
|
47417
|
+
/** Scans maintained text files without following symlinks or inspecting runtime state. */
|
|
47418
|
+
async function visit(relativeDirectory) {
|
|
47419
|
+
let entries;
|
|
47420
|
+
try {
|
|
47421
|
+
entries = await promises.readdir(path.join(projectPath, relativeDirectory), { withFileTypes: true });
|
|
47422
|
+
}
|
|
47423
|
+
catch (_a) {
|
|
47424
|
+
for (const legacyName of legacyNames)
|
|
47425
|
+
callers[legacyName].push(`${relativeDirectory} (unreadable directory; review manually)`);
|
|
47426
|
+
return;
|
|
47427
|
+
}
|
|
47428
|
+
for (const entry of entries) {
|
|
47429
|
+
const relativePath = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
|
|
47430
|
+
if (entry.isSymbolicLink()) {
|
|
47431
|
+
if (!IGNORED_CALLER_DIRECTORIES.has(entry.name)) {
|
|
47432
|
+
for (const legacyName of legacyNames)
|
|
47433
|
+
callers[legacyName].push(`${relativePath} (symbolic link; review manually)`);
|
|
47434
|
+
}
|
|
47435
|
+
continue;
|
|
47436
|
+
}
|
|
47437
|
+
if (entry.isDirectory()) {
|
|
47438
|
+
if (!IGNORED_CALLER_DIRECTORIES.has(entry.name) && !IGNORED_CALLER_HISTORY_PATHS.has(relativePath))
|
|
47439
|
+
await visit(relativePath);
|
|
47440
|
+
}
|
|
47441
|
+
else if (entry.isFile() && (CALLER_FILE_PATTERN.test(entry.name) || CALLER_FILE_NAMES.has(entry.name))) {
|
|
47442
|
+
try {
|
|
47443
|
+
let content = await promises.readFile(path.join(projectPath, relativePath), 'utf-8');
|
|
47444
|
+
if (relativePath === 'package.json') {
|
|
47445
|
+
// Script callers are already handled by the merge. Other project-owned metadata may also
|
|
47446
|
+
// reference a script, so it must be included when deciding whether removal is safe.
|
|
47447
|
+
const packageMetadata = JSON.parse(content);
|
|
47448
|
+
delete packageMetadata.scripts;
|
|
47449
|
+
content = JSON.stringify(packageMetadata);
|
|
47450
|
+
}
|
|
47451
|
+
for (const legacyName of legacyNames) {
|
|
47452
|
+
if (content.includes(legacyName))
|
|
47453
|
+
callers[legacyName].push(relativePath === 'package.json' ? 'package.json (outside scripts)' : relativePath);
|
|
47454
|
+
}
|
|
47455
|
+
}
|
|
47456
|
+
catch (_b) {
|
|
47457
|
+
// An unreadable file cannot prove that deletion is safe. Keep the entry and explain why.
|
|
47458
|
+
for (const legacyName of legacyNames)
|
|
47459
|
+
callers[legacyName].push(`${relativePath} (unreadable; review manually)`);
|
|
47460
|
+
}
|
|
47461
|
+
}
|
|
47462
|
+
}
|
|
47463
|
+
}
|
|
47464
|
+
await visit('');
|
|
47465
|
+
return callers;
|
|
47466
|
+
}
|
|
47467
|
+
|
|
46893
47468
|
/**
|
|
46894
47469
|
* Relative path to `package.json` in the initialized project.
|
|
46895
47470
|
*/
|
|
@@ -46897,17 +47472,30 @@
|
|
|
46897
47472
|
/**
|
|
46898
47473
|
* Ensures `package.json` contains the standalone Promptbook coder helper scripts.
|
|
46899
47474
|
*
|
|
46900
|
-
*
|
|
47475
|
+
* Project definitions are preserved; missing scripts and narrowly recognized generated migrations are applied.
|
|
46901
47476
|
*
|
|
46902
47477
|
* @private function of `initializeCoderProjectConfiguration`
|
|
46903
47478
|
*/
|
|
46904
47479
|
async function ensureCoderPackageJsonFile(projectPath) {
|
|
46905
|
-
|
|
47480
|
+
let preparation;
|
|
47481
|
+
const mergedFile = await mergeStringRecordJsonFile({
|
|
46906
47482
|
projectPath,
|
|
46907
47483
|
relativeFilePath: PACKAGE_JSON_FILE_PATH,
|
|
46908
47484
|
fieldPath: 'scripts',
|
|
46909
47485
|
nextEntries: getDefaultCoderPackageJsonScripts(),
|
|
47486
|
+
transformExistingEntries: async (entries) => {
|
|
47487
|
+
const legacyNames = Object.keys(entries).filter((name) => name === 'test-for-ptbk-coder' || name === 'check-for-ptbk-coder');
|
|
47488
|
+
const externalCallers = await findLegacyCoderCheckCallers(projectPath, legacyNames);
|
|
47489
|
+
preparation = prepareCoderPackageJsonScripts(entries, externalCallers);
|
|
47490
|
+
return preparation.scripts;
|
|
47491
|
+
},
|
|
46910
47492
|
});
|
|
47493
|
+
return {
|
|
47494
|
+
...mergedFile,
|
|
47495
|
+
checkScriptSummary: preparation.checkScriptSummary,
|
|
47496
|
+
migrationInstructions: preparation.migrationInstructions,
|
|
47497
|
+
isCheckConfigured: preparation.isCheckConfigured,
|
|
47498
|
+
};
|
|
46911
47499
|
}
|
|
46912
47500
|
// Note: [🟡] Code for coder init package.json bootstrapping [ensureCoderPackageJsonFile](src/cli/cli-commands/coder/ensureCoderPackageJsonFile.ts) should never be published outside of `@promptbook/cli`
|
|
46913
47501
|
|
|
@@ -47201,9 +47789,9 @@
|
|
|
47201
47789
|
|
|
47202
47790
|
Runner-written completion lines may attribute implementation to a harness and model, include
|
|
47203
47791
|
reasoning/authentication labels, attempts or interrupted/continued history, and report implementation,
|
|
47204
|
-
|
|
47205
|
-
or a frozen list of supported models. A completed status alone does not prove
|
|
47206
|
-
execute
|
|
47792
|
+
checking, fixing, or total cost/time information. Those are observed run metadata, not instructions, budgets,
|
|
47793
|
+
or a frozen list of supported models. A completed status alone does not prove checks ran: direct runs only
|
|
47794
|
+
execute the project check command when configured. Preserve actual measurements and record unknown
|
|
47207
47795
|
results or checks that were not run honestly. Manual users must not invent cost/time figures, copy another
|
|
47208
47796
|
run's attribution, or mark unverified work as verified. The textual metadata rows above demonstrate syntax
|
|
47209
47797
|
only; use them only when the described events actually happened.
|
|
@@ -47254,9 +47842,9 @@
|
|
|
47254
47842
|
| ----------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
47255
47843
|
| \`ptbk init\` / \`ptbk coder init\` | Initializes missing Git, then creates missing configuration, local Books, this guide, and fresh-directory boilerplates; preserves project-owned content. \`--no-questions\` skips installation questions/checks. |
|
|
47256
47844
|
| \`ptbk coder add "Describe the reviewed change"\` | Creates one numbered, tagged pending PRD. Accepts a description argument, stdin, or interactive input; \`--priority\` and \`--template\` are available. It does not discuss or implement the task. Review the generated requirements before running. |
|
|
47257
|
-
| \`ptbk coder plan --harness openai-codex\` | Interactive planning with the local
|
|
47845
|
+
| \`ptbk coder plan --harness openai-codex\` | Interactive planning with the local Developer. Review proposals; \`/save\` writes pending PRDs, \`/draft\` writes not-ready drafts, \`/discard\` drops proposals, \`/exit\` ends. It changes PRD Markdown only and never implements or starts the queue. Currently this planning command supports the Codex harness in a compatible interactive terminal. |
|
|
47258
47846
|
| \`ptbk coder list\` | Displays fully authored pending tasks grouped by descending priority without execution or file changes. Optional harness/model/agent and priority filters narrow the list. |
|
|
47259
|
-
| \`ptbk coder run --harness openai-codex --limit 1 --no-commit --no-auto --
|
|
47847
|
+
| \`ptbk coder run --harness openai-codex --limit 1 --no-commit --no-auto --check "npm run check"\` | Confirms and implements one selected task, then runs the specified project check. Replace the check command as needed. Without \`--limit\`, execution proceeds through the eligible queue; without \`--no-commit\`, run stages and commits its changes. |
|
|
47260
47848
|
| \`ptbk coder verify\` | Human review helper: shows completion claims, offers archival or a repair section, and can also ask about pending tasks. It does not run acceptance tests itself. Archival moves the whole file to \`done/\`, so inspect every section before agreeing. There is no separate archive command. |
|
|
47261
47849
|
| \`ptbk coder find-unwritten\` | Lists pending sections still containing authoring placeholders; not-ready drafts are not included. |
|
|
47262
47850
|
| \`ptbk coder generate-boilerplates\` | Adds not-ready starter sections using reusable templates; author and review them before making them pending. |
|
|
@@ -47268,11 +47856,18 @@
|
|
|
47268
47856
|
pulling require the corresponding explicit options. Consult \`ptbk coder --help\` and the relevant subcommand's
|
|
47269
47857
|
\`--help\` for the installed version's full options.
|
|
47270
47858
|
|
|
47271
|
-
The initialized \`npm run coder:run\` script
|
|
47272
|
-
|
|
47273
|
-
|
|
47274
|
-
|
|
47275
|
-
|
|
47859
|
+
The initialized \`npm run coder:run\` script selects the Codex harness and uses
|
|
47860
|
+
\`--check "npm run check" --check-before yes-and-fix\`. Developer, the current project directory, and its
|
|
47861
|
+
\`AGENTS.md\` are shared CLI defaults. A **check** covers the project's chosen tests, linting, typechecking,
|
|
47862
|
+
builds, generated-code consistency, and other validation. Tests remain one kind of check.
|
|
47863
|
+
Init preserves an existing \`scripts.check\` exactly, or composes applicable existing validation scripts and
|
|
47864
|
+
reports the selected scope. If none are usable, it creates a failing setup placeholder: configure real
|
|
47865
|
+
validation before running Coder. Missing checks or setup placeholders stop with setup guidance, without model repairs.
|
|
47866
|
+
Direct \`ptbk coder run\` defaults to \`--check-before no\`; checks after prompts remain opt-in. Enabled
|
|
47867
|
+
preflight without an explicit command uses \`npm run check\`, including during repair verification.
|
|
47868
|
+
Replace retired \`--test\` / \`--test-before\` with \`--check\` / \`--check-before\`. Init migrates recognized
|
|
47869
|
+
generated scripts and preserves custom legacy validation in \`check\`. Conflicting definitions or custom callers
|
|
47870
|
+
are preserved with manual migration instructions; review them before removing a legacy script.
|
|
47276
47871
|
|
|
47277
47872
|
### Book agent, harness, and model
|
|
47278
47873
|
|
|
@@ -47284,9 +47879,20 @@
|
|
|
47284
47879
|
Init creates local Developer and Planner Books in \`agents/developer.book\` and \`agents/planner.book\`, their
|
|
47285
47880
|
Lawyer and Copywriter TEAM advisers, and shared \`agents/.core/adam.book\` instructions. Books can
|
|
47286
47881
|
inherit/import instructions; TEAM entries expose advisers for relevant consultations, not an obligation to
|
|
47287
|
-
invoke everyone. \`run
|
|
47288
|
-
\`--agent agents/
|
|
47289
|
-
|
|
47882
|
+
invoke everyone. \`run\`, \`server\` and \`plan\` default to Developer.
|
|
47883
|
+
\`--agent ./agents/planner.book\` selects Planner explicitly; another Book path also works. \`list\` has no
|
|
47884
|
+
default Book filter. Every Book used in \`plan\`, including Developer, still permits planning only.
|
|
47885
|
+
|
|
47886
|
+
Project commands default to the current directory captured when invoked. \`--path\` selects another existing
|
|
47887
|
+
directory, relative to that invocation or absolute; an enclosing Git repository never relocates the project's
|
|
47888
|
+
Books, PRDs or context. Additional context defaults to the actual UTF-8 contents of that project's \`AGENTS.md\`.
|
|
47889
|
+
A missing implicit file warns and continues; an unreadable file fails. \`--context\` replaces the default with
|
|
47890
|
+
inline instructions or a file resolved relative to the selected project; \`--context ""\` disables it.
|
|
47891
|
+
Invalid explicit Books and missing/unreadable explicit context files fail without falling back.
|
|
47892
|
+
Thus \`ptbk coder run --harness openai-codex\` and
|
|
47893
|
+
\`ptbk coder run --harness openai-codex --agent ./agents/developer.book --path . --context ./AGENTS.md\` select
|
|
47894
|
+
the same inputs. New npm scripts rely on these defaults; init still creates missing Books and AGENTS.md even
|
|
47895
|
+
when every script already exists, preserving existing custom scripts, settings and context.
|
|
47290
47896
|
|
|
47291
47897
|
Edit local Books to reflect this project's rules; repeat init preserves customizations and adds missing
|
|
47292
47898
|
defaults/helper references. An invalid explicit Book selection fails rather than silently changing roles.
|
|
@@ -47357,7 +47963,7 @@
|
|
|
47357
47963
|
const adamArtifact = defaultAgentArtifacts.find(({ relativeFilePath }) => relativeFilePath === adamRelativeFilePath);
|
|
47358
47964
|
const { envFileStatus, initializedEnvVariableNames } = await completeStep('.env', ensureCoderEnvFile(projectPath));
|
|
47359
47965
|
const gitignoreFileStatus = await completeStep('.gitignore', ensureCoderGitignoreFile(projectPath));
|
|
47360
|
-
const { status: packageJsonFileStatus, addedEntryKeys: addedPackageJsonScriptNames } = await completeStep('package.json', ensureCoderPackageJsonFile(projectPath));
|
|
47966
|
+
const { status: packageJsonFileStatus, addedEntryKeys: addedPackageJsonScriptNames, checkScriptSummary, migrationInstructions, isCheckConfigured, } = await completeStep('package.json', ensureCoderPackageJsonFile(projectPath));
|
|
47361
47967
|
const vscodeSettingsFileStatus = await completeStep('.vscode/settings.json', ensureCoderVscodeSettingsFile(projectPath));
|
|
47362
47968
|
const referencedArtifactStatuses = [
|
|
47363
47969
|
...defaultAgentArtifacts.filter(({ relativeFilePath }) => relativeFilePath !== adamRelativeFilePath),
|
|
@@ -47378,6 +47984,9 @@
|
|
|
47378
47984
|
addedPackageJsonScriptNames,
|
|
47379
47985
|
referencedArtifactStatuses,
|
|
47380
47986
|
initializedEnvVariableNames,
|
|
47987
|
+
checkScriptSummary,
|
|
47988
|
+
migrationInstructions,
|
|
47989
|
+
isCheckConfigured,
|
|
47381
47990
|
};
|
|
47382
47991
|
}
|
|
47383
47992
|
// Note: [🟡] Code for coder init project bootstrapping [initializeCoderProjectConfiguration](src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -47389,9 +47998,11 @@
|
|
|
47389
47998
|
*/
|
|
47390
47999
|
function printInitializationSummary(summary, workspace) {
|
|
47391
48000
|
const isUnresolved = summary.adamAgentFileStatus === 'unresolved' ||
|
|
48001
|
+
!summary.isCheckConfigured ||
|
|
48002
|
+
summary.migrationInstructions.length > 0 ||
|
|
47392
48003
|
summary.referencedArtifactStatuses.some(({ status }) => status === 'unresolved');
|
|
47393
48004
|
console.info(isUnresolved
|
|
47394
|
-
? colors__default["default"].yellow('Promptbook coder
|
|
48005
|
+
? colors__default["default"].yellow('Promptbook coder configuration setup: additional setup is required.')
|
|
47395
48006
|
: colors__default["default"].green('Promptbook coder configuration setup:'));
|
|
47396
48007
|
if (workspace)
|
|
47397
48008
|
console.info(colors__default["default"].gray(`✔ Git repository: ${workspace.repositoryStatus} (${workspace.repositoryRoot})`));
|
|
@@ -47420,6 +48031,9 @@
|
|
|
47420
48031
|
else {
|
|
47421
48032
|
printInitializationNote('Required coder env variables are already present.', colors__default["default"].gray);
|
|
47422
48033
|
}
|
|
48034
|
+
console.info((summary.isCheckConfigured ? colors__default["default"].cyan : colors__default["default"].yellow)(summary.checkScriptSummary));
|
|
48035
|
+
for (const instruction of summary.migrationInstructions)
|
|
48036
|
+
console.info(colors__default["default"].yellow(`! ${instruction}`));
|
|
47423
48037
|
}
|
|
47424
48038
|
/**
|
|
47425
48039
|
* Formats one initialization status into a human-readable label.
|
|
@@ -47501,7 +48115,7 @@
|
|
|
47501
48115
|
- Adds missing local Lawyer and Copywriter TEAM references to Developer and Planner, preserving existing content
|
|
47502
48116
|
- Helpers advise on relevant tasks; declaring TEAM does not run them for every task
|
|
47503
48117
|
- Reports created, augmented, unchanged and unresolved Books; invalid or conflicting files are left untouched
|
|
47504
|
-
-
|
|
48118
|
+
- Missing AGENTS.md is initialized independently of scripts; existing content is preserved
|
|
47505
48119
|
|
|
47506
48120
|
Ensures required coding-agent environment variables in .env:
|
|
47507
48121
|
- CODING_AGENT_GIT_NAME
|
|
@@ -47519,9 +48133,14 @@
|
|
|
47519
48133
|
addQuestionsOption(command);
|
|
47520
48134
|
addWorkspaceRepositoryOptions(command);
|
|
47521
48135
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
48136
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
47522
48137
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
47523
48138
|
const questionsOptions = normalizeQuestionsCliOptions(cliOptions);
|
|
47524
|
-
const workspace = await $preflightWorkspaceRepository({
|
|
48139
|
+
const workspace = await $preflightWorkspaceRepository({
|
|
48140
|
+
...projectOptions,
|
|
48141
|
+
policy: 'initialize',
|
|
48142
|
+
...questionsOptions,
|
|
48143
|
+
});
|
|
47525
48144
|
const { projectPath } = workspace;
|
|
47526
48145
|
const completedSteps = [`Git repository ${workspace.repositoryStatus}: ${workspace.repositoryRoot}`];
|
|
47527
48146
|
try {
|
|
@@ -47635,6 +48254,11 @@
|
|
|
47635
48254
|
developer: CODER_DEVELOPER_AGENT_FILE_PATH,
|
|
47636
48255
|
planner: CODER_PLANNER_AGENT_FILE_PATH,
|
|
47637
48256
|
};
|
|
48257
|
+
/**
|
|
48258
|
+
* Shared persona for optional single-agent execution and authoring; capabilities belong to the command.
|
|
48259
|
+
* @private internal constant of project CLI commands
|
|
48260
|
+
*/
|
|
48261
|
+
const DEFAULT_CODER_AGENT_ROLE = 'developer';
|
|
47638
48262
|
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
47639
48263
|
|
|
47640
48264
|
/**
|
|
@@ -47654,6 +48278,14 @@
|
|
|
47654
48278
|
: 'No default Book filter; omitting --agent includes tasks for all agents';
|
|
47655
48279
|
command.option('--agent <agent-book-path>', `${CODER_AGENT_OPTION_DESCRIPTION}. ${defaultDescription}`);
|
|
47656
48280
|
}
|
|
48281
|
+
/**
|
|
48282
|
+
* Registers the shared optional persona and context for single-agent execution or authoring.
|
|
48283
|
+
* @private internal CLI registration helper
|
|
48284
|
+
*/
|
|
48285
|
+
function addCoderExecutionOptions(command) {
|
|
48286
|
+
addCoderAgentOption(command, DEFAULT_CODER_AGENT_ROLE);
|
|
48287
|
+
addProjectContextOption(command);
|
|
48288
|
+
}
|
|
47657
48289
|
// Note: [🟡] Code for CLI coder agent options should never be published outside of `@promptbook/cli`
|
|
47658
48290
|
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
47659
48291
|
|
|
@@ -47682,9 +48314,13 @@
|
|
|
47682
48314
|
addPromptPriorityOptions(command);
|
|
47683
48315
|
addWorkspaceRepositoryOptions(command);
|
|
47684
48316
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
48317
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
47685
48318
|
const { agent, priority, minPriority: minimumPriority, maxPriority: maximumPriority, } = cliOptions;
|
|
47686
48319
|
const runnerOptions = normalizePromptRunnerSelectionCliOptions(cliOptions, { isAgentRequired: false });
|
|
47687
|
-
const workspace = await $preflightWorkspaceRepository({
|
|
48320
|
+
const workspace = await $preflightWorkspaceRepository({
|
|
48321
|
+
...projectOptions,
|
|
48322
|
+
policy: 'read-only',
|
|
48323
|
+
});
|
|
47688
48324
|
const resolvedCoderAgentBook = agent === undefined
|
|
47689
48325
|
? undefined
|
|
47690
48326
|
: await (await Promise.resolve().then(function () { return resolveCoderAgent$1; })).resolveCoderAgentBook(agent, workspace.projectPath);
|
|
@@ -47825,12 +48461,17 @@
|
|
|
47825
48461
|
`));
|
|
47826
48462
|
addWorkspaceRepositoryOptions(command);
|
|
47827
48463
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
48464
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
47828
48465
|
const { period: periodValue } = cliOptions;
|
|
47829
48466
|
const runnerOptions = normalizePromptRunnerSelectionCliOptions(cliOptions, { isAgentRequired: true });
|
|
47830
48467
|
const questionsOptions = normalizeQuestionsCliOptions(cliOptions);
|
|
47831
48468
|
// Note: The period is validated before the harness installation check, so a mistyped duration fails fast
|
|
47832
48469
|
const periodMs = parseOptionalPeriodDuration('--period', periodValue);
|
|
47833
|
-
const workspace = await $preflightWorkspaceRepository({
|
|
48470
|
+
const workspace = await $preflightWorkspaceRepository({
|
|
48471
|
+
...projectOptions,
|
|
48472
|
+
policy: 'mutate',
|
|
48473
|
+
...questionsOptions,
|
|
48474
|
+
});
|
|
47834
48475
|
await $ensureHarnessInstallations([runnerOptions.agentName], questionsOptions);
|
|
47835
48476
|
await $ensureCoderHarnessGitignoreRules(workspace.projectPath, runnerOptions.agentName, questionsOptions);
|
|
47836
48477
|
const pingOptions = {
|
|
@@ -47862,10 +48503,10 @@
|
|
|
47862
48503
|
*/
|
|
47863
48504
|
function $initializeCoderPlanCommand(program) {
|
|
47864
48505
|
const command = program.command('plan').description(spaceTrim(`
|
|
47865
|
-
Discuss features with the project's
|
|
48506
|
+
Discuss features with the project's Developer Book and review PRDs before saving them.
|
|
47866
48507
|
|
|
47867
|
-
Run ptbk coder init first. Default Book: agents/
|
|
47868
|
-
independently of --harness and --model. Currently supports openai-codex with restricted tools.
|
|
48508
|
+
Run ptbk coder init first. Default Book: agents/developer.book; --agent overrides the Book,
|
|
48509
|
+
independently of --harness and --model. Use --agent ./agents/planner.book for Planner. Currently supports openai-codex with restricted tools.
|
|
47869
48510
|
Requires an interactive terminal and a Codex version supporting --ignore-user-config and --ignore-rules.
|
|
47870
48511
|
Codex configuration, plugins, hooks and native tools are isolated; --model default uses Codex's built-in default.
|
|
47871
48512
|
/save applies reviewed proposals, /draft saves [-] drafts, /discard drops proposals, /exit ends.
|
|
@@ -47874,11 +48515,12 @@
|
|
|
47874
48515
|
`));
|
|
47875
48516
|
addPromptRunnerSelectionOptions(command);
|
|
47876
48517
|
addPromptRunnerRuntimeOptions(command);
|
|
47877
|
-
|
|
48518
|
+
addCoderExecutionOptions(command);
|
|
47878
48519
|
addCoderGitSyncOptions(command);
|
|
47879
48520
|
command.option('--template <path>', 'PRD template (defaults to the project-owned prompts/templates/common.md when present)');
|
|
47880
48521
|
addWorkspaceRepositoryOptions(command);
|
|
47881
48522
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
48523
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
47882
48524
|
const { createPlanningTerminal } = await Promise.resolve().then(function () { return createPlanningTerminal$1; });
|
|
47883
48525
|
const { runPlanningSession } = await Promise.resolve().then(function () { return runPlanningSession$1; });
|
|
47884
48526
|
const { resolvePlanningPath } = await Promise.resolve().then(function () { return resolvePlanningPath$1; });
|
|
@@ -47889,12 +48531,18 @@
|
|
|
47889
48531
|
assertPlanningHarnessSupported(options.agentName);
|
|
47890
48532
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
47891
48533
|
const workspace = await $preflightWorkspaceRepository({
|
|
48534
|
+
...projectOptions,
|
|
47892
48535
|
policy: 'mutate',
|
|
47893
48536
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
47894
48537
|
});
|
|
47895
48538
|
if (cliOptions.questions === false) {
|
|
47896
48539
|
throw new NotAllowed(spaceTrim('`ptbk coder plan` requires an interactive conversation and review. Run it without `--no-questions` in a terminal.'));
|
|
47897
48540
|
}
|
|
48541
|
+
const { resolveCoderProjectContext } = await Promise.resolve().then(function () { return resolveCoderProjectContext$1; });
|
|
48542
|
+
const projectContext = await resolveCoderProjectContext({
|
|
48543
|
+
...cliOptions,
|
|
48544
|
+
projectPath: workspace.projectPath,
|
|
48545
|
+
});
|
|
47898
48546
|
const terminal = createPlanningTerminal();
|
|
47899
48547
|
try {
|
|
47900
48548
|
const { projectPath } = workspace;
|
|
@@ -47907,6 +48555,8 @@
|
|
|
47907
48555
|
...options,
|
|
47908
48556
|
projectPath,
|
|
47909
48557
|
agent: cliOptions.agent,
|
|
48558
|
+
context: cliOptions.context,
|
|
48559
|
+
projectContext,
|
|
47910
48560
|
template: cliOptions.template,
|
|
47911
48561
|
preexistingChangedPaths: gitSync.isCommitEnabled
|
|
47912
48562
|
? new Set(Array.from(commitScope.snapshotBeforeOperation.changedFileHashes.keys(), (path$1) => path.relative(projectPath, path.join(workspace.repositoryRoot, path$1)).replace(/\\/gu, '/')))
|
|
@@ -48096,30 +48746,20 @@
|
|
|
48096
48746
|
}
|
|
48097
48747
|
// Note: [🟡] Code for CLI free disk space handling [$assertSufficientFreeDiskSpace](src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.ts) should never be published outside of `@promptbook/cli`
|
|
48098
48748
|
|
|
48099
|
-
/**
|
|
48100
|
-
* Modes supported by `ptbk coder run --test-before`.
|
|
48101
|
-
*/
|
|
48102
|
-
const TEST_BEFORE_MODE_VALUES = ['no', 'yes-and-fail', 'yes-and-fix'];
|
|
48103
|
-
/**
|
|
48104
|
-
* Default verification command used when a pre-coding mode is enabled without an explicit `--test` command.
|
|
48105
|
-
*/
|
|
48106
|
-
const DEFAULT_CODER_TEST_COMMAND = 'npm test';
|
|
48107
|
-
/**
|
|
48108
|
-
* Checks whether a value is a supported `--test-before` mode.
|
|
48109
|
-
*/
|
|
48110
|
-
function isTestBeforeMode(value) {
|
|
48111
|
-
return TEST_BEFORE_MODE_VALUES.includes(value);
|
|
48112
|
-
}
|
|
48113
|
-
|
|
48114
48749
|
/**
|
|
48115
48750
|
* Validates cross-flag constraints before workspace setup or the run starts.
|
|
48116
48751
|
* @private shared validation for Coder execution commands
|
|
48117
48752
|
*/
|
|
48118
48753
|
function validateCoderRunOptions(options) {
|
|
48119
48754
|
var _a;
|
|
48120
|
-
if (
|
|
48755
|
+
if (options.checkCommand !== undefined && !options.checkCommand.trim()) {
|
|
48121
48756
|
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
48122
|
-
|
|
48757
|
+
Option \`--check\` requires a non-empty shell command, for example \`npm run check\`.
|
|
48758
|
+
`));
|
|
48759
|
+
}
|
|
48760
|
+
if (!isCheckBeforeMode((_a = options.checkBefore) !== null && _a !== void 0 ? _a : 'no')) {
|
|
48761
|
+
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
48762
|
+
Invalid ${'`--check-before`'} mode: \`${String(options.checkBefore)}\`.
|
|
48123
48763
|
|
|
48124
48764
|
Use one of: \`no\`, \`yes-and-fail\`, \`yes-and-fix\`.
|
|
48125
48765
|
`));
|
|
@@ -48157,9 +48797,9 @@
|
|
|
48157
48797
|
An isolated task is implemented in a fresh temporary worktree checked out from the last commit, so the uncommitted changes of the interrupted prompt would be left behind instead of being continued.
|
|
48158
48798
|
`));
|
|
48159
48799
|
}
|
|
48160
|
-
if (options.gitChanges === 'continue' && options.
|
|
48800
|
+
if (options.gitChanges === 'continue' && options.checkBefore === 'yes-and-fix') {
|
|
48161
48801
|
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
48162
|
-
Flag \`--git-changes continue\` cannot be combined with \`--
|
|
48802
|
+
Flag \`--git-changes continue\` cannot be combined with \`--check-before yes-and-fix\`.
|
|
48163
48803
|
|
|
48164
48804
|
An interrupted prompt already has changes in progress, so there is no unmodified project state for pre-coding verification to repair.
|
|
48165
48805
|
`));
|
|
@@ -48206,9 +48846,9 @@
|
|
|
48206
48846
|
*
|
|
48207
48847
|
* @private internal utility of `promptbookCli`
|
|
48208
48848
|
*/
|
|
48209
|
-
async function $resolvePromptbookCliInstallations() {
|
|
48849
|
+
async function $resolvePromptbookCliInstallations(projectPath = process.cwd()) {
|
|
48210
48850
|
const [localInstallations, globalInstallations] = await Promise.all([
|
|
48211
|
-
$resolveLocalPromptbookCliInstallations(),
|
|
48851
|
+
$resolveLocalPromptbookCliInstallations(projectPath),
|
|
48212
48852
|
$resolveGlobalPromptbookCliInstallations(),
|
|
48213
48853
|
]);
|
|
48214
48854
|
return [...localInstallations, ...globalInstallations];
|
|
@@ -48216,8 +48856,8 @@
|
|
|
48216
48856
|
/**
|
|
48217
48857
|
* Finds the closest ancestor `package.json` which directly declares a Promptbook CLI package.
|
|
48218
48858
|
*/
|
|
48219
|
-
async function $resolveLocalPromptbookCliInstallations() {
|
|
48220
|
-
let candidateProjectPath = path.resolve(
|
|
48859
|
+
async function $resolveLocalPromptbookCliInstallations(projectPath) {
|
|
48860
|
+
let candidateProjectPath = path.resolve(projectPath);
|
|
48221
48861
|
let isFileSystemRootReached = false;
|
|
48222
48862
|
while (!isFileSystemRootReached) {
|
|
48223
48863
|
const projectPackageJson = await $readJsonObject(path.join(candidateProjectPath, PACKAGE_JSON_FILENAME));
|
|
@@ -48373,8 +49013,8 @@
|
|
|
48373
49013
|
*
|
|
48374
49014
|
* @private internal utility of `promptbookCli`
|
|
48375
49015
|
*/
|
|
48376
|
-
async function $checkPromptbookCliInstallations() {
|
|
48377
|
-
const installations = await $resolvePromptbookCliInstallations();
|
|
49016
|
+
async function $checkPromptbookCliInstallations(projectPath = process.cwd()) {
|
|
49017
|
+
const installations = await $resolvePromptbookCliInstallations(projectPath);
|
|
48378
49018
|
if (installations.length === 0) {
|
|
48379
49019
|
return [];
|
|
48380
49020
|
}
|
|
@@ -48429,10 +49069,10 @@
|
|
|
48429
49069
|
* @returns `true` when the package update succeeds, `false` when it fails
|
|
48430
49070
|
* @private internal utility of `promptbookCli`
|
|
48431
49071
|
*/
|
|
48432
|
-
async function $updatePromptbookCliInstallation(status) {
|
|
49072
|
+
async function $updatePromptbookCliInstallation(status, projectPath = process.cwd()) {
|
|
48433
49073
|
const { npmPackageName, installationLocation } = status.installation;
|
|
48434
49074
|
const installCommand = buildPromptbookCliInstallCommand(status.installation);
|
|
48435
|
-
const updateWorkingDirectory = installationLocation === 'global' ?
|
|
49075
|
+
const updateWorkingDirectory = installationLocation === 'global' ? projectPath : status.installation.projectPath;
|
|
48436
49076
|
console.info(colors__default["default"].cyan(`Updating Promptbook CLI package \`${npmPackageName}\` with \`${installCommand}\`...`));
|
|
48437
49077
|
try {
|
|
48438
49078
|
await $execCommand({
|
|
@@ -48502,7 +49142,7 @@
|
|
|
48502
49142
|
* @returns `true` when at least one installation was updated and the current coder run should stop
|
|
48503
49143
|
* @private internal utility of `promptbookCli`
|
|
48504
49144
|
*/
|
|
48505
|
-
async function $ensurePromptbookCliInstallations(questionsOptions) {
|
|
49145
|
+
async function $ensurePromptbookCliInstallations(questionsOptions, projectPath = process.cwd()) {
|
|
48506
49146
|
if (!questionsOptions.isAskingQuestionsEnabled) {
|
|
48507
49147
|
// Note: `--no-questions` forbids asking for the approval, so the registry checks would be useless
|
|
48508
49148
|
return false;
|
|
@@ -48511,7 +49151,7 @@
|
|
|
48511
49151
|
// Note: Non-interactive runs cannot approve an update and should not wait for registry checks
|
|
48512
49152
|
return false;
|
|
48513
49153
|
}
|
|
48514
|
-
const statuses = await $checkPromptbookCliInstallations();
|
|
49154
|
+
const statuses = await $checkPromptbookCliInstallations(projectPath);
|
|
48515
49155
|
const outdatedStatuses = statuses.filter(({ installationState }) => installationState === 'outdated');
|
|
48516
49156
|
if (outdatedStatuses.length === 0) {
|
|
48517
49157
|
reportPromptbookCliInstallationStatuses(statuses);
|
|
@@ -48525,7 +49165,7 @@
|
|
|
48525
49165
|
}
|
|
48526
49166
|
const updateResults = [];
|
|
48527
49167
|
for (const status of outdatedStatuses) {
|
|
48528
|
-
updateResults.push(await $updatePromptbookCliInstallation(status));
|
|
49168
|
+
updateResults.push(await $updatePromptbookCliInstallation(status, projectPath));
|
|
48529
49169
|
}
|
|
48530
49170
|
const isAnyInstallationUpdated = updateResults.some(Boolean);
|
|
48531
49171
|
const isEveryInstallationUpdated = updateResults.every(Boolean);
|
|
@@ -48570,6 +49210,89 @@
|
|
|
48570
49210
|
}
|
|
48571
49211
|
// Note: [🟡] Code for Promptbook CLI installation orchestration [$ensurePromptbookCliInstallations](src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.ts) should never be published outside of `@promptbook/cli`
|
|
48572
49212
|
|
|
49213
|
+
/** Standalone shell composition tokens remain operators when a command is supplied as several arguments. */
|
|
49214
|
+
const SHELL_COMPOSITION_TOKENS = new Set([
|
|
49215
|
+
'&&',
|
|
49216
|
+
'||',
|
|
49217
|
+
'|',
|
|
49218
|
+
'|&',
|
|
49219
|
+
'&',
|
|
49220
|
+
';',
|
|
49221
|
+
'(',
|
|
49222
|
+
')',
|
|
49223
|
+
'>',
|
|
49224
|
+
'>>',
|
|
49225
|
+
'<',
|
|
49226
|
+
'2>',
|
|
49227
|
+
'2>>',
|
|
49228
|
+
'2>&1',
|
|
49229
|
+
]);
|
|
49230
|
+
/**
|
|
49231
|
+
* Retired aggregate option spellings and their canonical replacements, used only for migration diagnostics.
|
|
49232
|
+
* @private shared CLI migration definitions for Coder execution
|
|
49233
|
+
*/
|
|
49234
|
+
const LEGACY_CODER_CHECK_OPTIONS = [
|
|
49235
|
+
['--test', '--check'],
|
|
49236
|
+
['--test-before', '--check-before'],
|
|
49237
|
+
];
|
|
49238
|
+
/**
|
|
49239
|
+
* Registers the shared project check command and rejects retired aggregate-test spellings.
|
|
49240
|
+
* @private shared CLI registration for Coder execution
|
|
49241
|
+
*/
|
|
49242
|
+
function addCoderCheckOptions(command, isCheckBeforeSupported) {
|
|
49243
|
+
command.option('--check <check-command...>', 'Run project checks after each prompt; quote the full command when it contains flags or shell composition');
|
|
49244
|
+
if (isCheckBeforeSupported) {
|
|
49245
|
+
command.addOption(new commander.Option('--check-before <mode>', `Check before coding: ${CHECK_BEFORE_MODE_VALUES.join(', ')} (defaults to no; uses npm run check when --check is omitted)`)
|
|
49246
|
+
.choices([...CHECK_BEFORE_MODE_VALUES])
|
|
49247
|
+
.default('no'));
|
|
49248
|
+
}
|
|
49249
|
+
// These diagnostic-only options never forward a value or start execution.
|
|
49250
|
+
for (const [legacyFlag, replacementFlag] of LEGACY_CODER_CHECK_OPTIONS) {
|
|
49251
|
+
command.addOption(new commander.Option(`${legacyFlag} [value...]`).hideHelp());
|
|
49252
|
+
command.on(`option:${legacyFlag.slice(2)}`, () => {
|
|
49253
|
+
command.error(formatLegacyCoderCheckOptionError(legacyFlag, replacementFlag));
|
|
49254
|
+
});
|
|
49255
|
+
}
|
|
49256
|
+
}
|
|
49257
|
+
/**
|
|
49258
|
+
* Builds the same actionable migration diagnostic for registered and direct-script entrypoints.
|
|
49259
|
+
* @private shared CLI diagnostic for Coder execution
|
|
49260
|
+
*/
|
|
49261
|
+
function formatLegacyCoderCheckOptionError(legacyFlag, replacementFlag) {
|
|
49262
|
+
return `Aggregate verification option \`${legacyFlag}\` was renamed to \`${replacementFlag}\`. Update your command and package.json scripts.`;
|
|
49263
|
+
}
|
|
49264
|
+
/**
|
|
49265
|
+
* Normalizes shell command tokens without parsing a quoted command again or losing spaced argument boundaries.
|
|
49266
|
+
* @private shared command normalization for Coder execution
|
|
49267
|
+
*/
|
|
49268
|
+
function normalizeCheckCommandOption(value) {
|
|
49269
|
+
var _a, _b;
|
|
49270
|
+
if (value === undefined)
|
|
49271
|
+
return undefined;
|
|
49272
|
+
const parts = typeof value === 'string' ? [value] : value;
|
|
49273
|
+
const firstPart = (_b = (_a = parts[0]) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : '';
|
|
49274
|
+
for (const [legacyFlag, replacementFlag] of LEGACY_CODER_CHECK_OPTIONS) {
|
|
49275
|
+
if (firstPart === legacyFlag || firstPart.startsWith(`${legacyFlag}=`)) {
|
|
49276
|
+
throw new NotAllowed(formatLegacyCoderCheckOptionError(legacyFlag, replacementFlag));
|
|
49277
|
+
}
|
|
49278
|
+
}
|
|
49279
|
+
const command = parts.length === 1
|
|
49280
|
+
? parts[0].trim()
|
|
49281
|
+
: parts
|
|
49282
|
+
.map((part) => !SHELL_COMPOSITION_TOKENS.has(part) && (!part || /[\s'"\\$`;&|<>()*?]/u.test(part))
|
|
49283
|
+
? quoteBashArgument(part)
|
|
49284
|
+
: part)
|
|
49285
|
+
.join(' ')
|
|
49286
|
+
.trim();
|
|
49287
|
+
if (!command || !firstPart || firstPart.startsWith('-')) {
|
|
49288
|
+
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
49289
|
+
Option \`--check\` requires a non-empty shell command, for example \`--check "npm run check"\`.
|
|
49290
|
+
`));
|
|
49291
|
+
}
|
|
49292
|
+
return command;
|
|
49293
|
+
}
|
|
49294
|
+
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
49295
|
+
|
|
48573
49296
|
/**
|
|
48574
49297
|
* Prints why a coder run has ended to the terminal.
|
|
48575
49298
|
*
|
|
@@ -48616,20 +49339,16 @@
|
|
|
48616
49339
|
- Offers to add missing project-local ignore rules for the selected harness
|
|
48617
49340
|
- In interactive mode, checks local and global Promptbook CLI installations and offers to update them
|
|
48618
49341
|
- Supports GPG signing of commits
|
|
48619
|
-
- Optional pre-coding
|
|
48620
|
-
- Optional post-prompt
|
|
49342
|
+
- Optional pre-coding check run that can stop or repair pre-existing failures
|
|
49343
|
+
- Optional post-prompt checks with check-feedback retries
|
|
48621
49344
|
- Progress tracking and interactive P/S/X terminal controls; O changes only the dashboard output view
|
|
48622
49345
|
- Dry-run mode to preview prompts
|
|
48623
49346
|
`));
|
|
48624
49347
|
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
48625
49348
|
addPromptRunnerSelectionOptions(command);
|
|
48626
49349
|
addQuestionsOption(command);
|
|
48627
|
-
|
|
48628
|
-
command
|
|
48629
|
-
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
48630
|
-
command.addOption(new commander.Option('--test-before <mode>', `Run tests before coding: ${TEST_BEFORE_MODE_VALUES.join(', ')} (defaults to no; uses npm test when --test is omitted)`)
|
|
48631
|
-
.choices([...TEST_BEFORE_MODE_VALUES])
|
|
48632
|
-
.default('no'));
|
|
49350
|
+
addCoderExecutionOptions(command);
|
|
49351
|
+
addCoderCheckOptions(command, true);
|
|
48633
49352
|
command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
|
|
48634
49353
|
addPromptRunnerExecutionOptions(command);
|
|
48635
49354
|
command.option('--isolate', _spaceTrim.spaceTrim(`
|
|
@@ -48658,9 +49377,9 @@
|
|
|
48658
49377
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
48659
49378
|
addWorkspaceRepositoryOptions(command);
|
|
48660
49379
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
48661
|
-
const
|
|
48662
|
-
const
|
|
48663
|
-
const
|
|
49380
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
49381
|
+
const { dryRun, agent, context, check, checkBefore, preserveLogs, isolate: isIsolated, priority, minPriority: minimumPriority, maxPriority: maximumPriority, limit, waitAfterPrompt: waitAfterPromptValue, waitBetweenPrompts: waitBetweenPromptsValue, waitAfterError: waitAfterErrorValue, auto, autoMigrate, allowDestructiveAutoMigrate, } = cliOptions;
|
|
49382
|
+
const checkCommand = resolveCoderCheckCommand(normalizeCheckCommandOption(check), checkBefore);
|
|
48664
49383
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
48665
49384
|
isAgentRequired: !dryRun,
|
|
48666
49385
|
});
|
|
@@ -48689,8 +49408,8 @@
|
|
|
48689
49408
|
model: runnerOptions.model,
|
|
48690
49409
|
agent,
|
|
48691
49410
|
context,
|
|
48692
|
-
|
|
48693
|
-
|
|
49411
|
+
checkCommand,
|
|
49412
|
+
checkBefore,
|
|
48694
49413
|
preserveLogs,
|
|
48695
49414
|
isIsolated,
|
|
48696
49415
|
noUi: runnerOptions.noUi,
|
|
@@ -48709,16 +49428,20 @@
|
|
|
48709
49428
|
};
|
|
48710
49429
|
validateCoderRunOptions(runOptions);
|
|
48711
49430
|
const workspace = await $preflightWorkspaceRepository({
|
|
49431
|
+
...projectOptions,
|
|
48712
49432
|
policy: dryRun ? 'read-only' : 'mutate',
|
|
48713
49433
|
...questionsOptions,
|
|
48714
49434
|
});
|
|
49435
|
+
const { resolveCoderProjectContext } = await Promise.resolve().then(function () { return resolveCoderProjectContext$1; });
|
|
49436
|
+
const projectContext = await resolveCoderProjectContext({
|
|
49437
|
+
projectPath: workspace.projectPath,
|
|
49438
|
+
agent,
|
|
49439
|
+
context,
|
|
49440
|
+
});
|
|
48715
49441
|
if (!dryRun) {
|
|
48716
|
-
// Reject missing or unreadable Books before offering installations or project configuration writes.
|
|
48717
|
-
const { resolveCoderAgentBook } = await Promise.resolve().then(function () { return resolveCoderAgent$1; });
|
|
48718
|
-
await resolveCoderAgentBook(agent, workspace.projectPath, { defaultRole: 'developer' });
|
|
48719
49442
|
// Check disk space before installations and repository writes; previews require no setup.
|
|
48720
49443
|
await $assertSufficientFreeDiskSpace(workspace.projectPath);
|
|
48721
|
-
if (await $ensurePromptbookCliInstallations(questionsOptions)) {
|
|
49444
|
+
if (await $ensurePromptbookCliInstallations(questionsOptions, workspace.projectPath)) {
|
|
48722
49445
|
return process.exit(0);
|
|
48723
49446
|
}
|
|
48724
49447
|
await $ensureHarnessInstallations([runnerOptions.agentName], questionsOptions);
|
|
@@ -48727,8 +49450,7 @@
|
|
|
48727
49450
|
// Note: Import the function dynamically to avoid loading heavy dependencies until needed
|
|
48728
49451
|
const { runCodexPrompts } = await Promise.resolve().then(function () { return runCodexPrompts$1; });
|
|
48729
49452
|
try {
|
|
48730
|
-
|
|
48731
|
-
await runCodexPrompts({ ...runOptions, workspace });
|
|
49453
|
+
await runCodexPrompts({ ...runOptions, workspace, projectContext });
|
|
48732
49454
|
}
|
|
48733
49455
|
catch (error) {
|
|
48734
49456
|
assertsError(error);
|
|
@@ -48738,23 +49460,6 @@
|
|
|
48738
49460
|
return process.exit(0);
|
|
48739
49461
|
}));
|
|
48740
49462
|
}
|
|
48741
|
-
/**
|
|
48742
|
-
* Joins one Commander option that may be parsed either as a single string or a variadic token array.
|
|
48743
|
-
*
|
|
48744
|
-
* @private internal utility of `coder run` command
|
|
48745
|
-
*/
|
|
48746
|
-
function normalizeCommandOptionValue$1(value) {
|
|
48747
|
-
if (value === undefined) {
|
|
48748
|
-
return undefined;
|
|
48749
|
-
}
|
|
48750
|
-
const parts = Array.isArray(value) ? value : [value];
|
|
48751
|
-
const normalizedValue = parts
|
|
48752
|
-
.map((part) => part.trim())
|
|
48753
|
-
.filter(Boolean)
|
|
48754
|
-
.join(' ')
|
|
48755
|
-
.trim();
|
|
48756
|
-
return normalizedValue === '' ? undefined : normalizedValue;
|
|
48757
|
-
}
|
|
48758
49463
|
// Note: [🟡] Code for CLI command [run](src/cli/cli-commands/coder/run.ts) should never be published outside of `@promptbook/cli`
|
|
48759
49464
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
48760
49465
|
|
|
@@ -48800,9 +49505,8 @@
|
|
|
48800
49505
|
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
48801
49506
|
addPromptRunnerSelectionOptions(command);
|
|
48802
49507
|
addQuestionsOption(command);
|
|
48803
|
-
|
|
48804
|
-
command
|
|
48805
|
-
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
49508
|
+
addCoderExecutionOptions(command);
|
|
49509
|
+
addCoderCheckOptions(command, false);
|
|
48806
49510
|
command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
|
|
48807
49511
|
addPromptRunnerExecutionOptions(command);
|
|
48808
49512
|
addPromptPriorityOptions(command);
|
|
@@ -48824,9 +49528,10 @@
|
|
|
48824
49528
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
48825
49529
|
addWorkspaceRepositoryOptions(command);
|
|
48826
49530
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
48827
|
-
const
|
|
49531
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
49532
|
+
const { port: rawPort, dryRun, agent, context, check, preserveLogs, priority, minPriority: minimumPriority, maxPriority: maximumPriority, waitAfterPrompt: waitAfterPromptValue, waitBetweenPrompts: waitBetweenPromptsValue, waitAfterError: waitAfterErrorValue, auto, autoMigrate, allowDestructiveAutoMigrate, } = cliOptions;
|
|
48828
49533
|
const port = parseCoderServerPort(rawPort);
|
|
48829
|
-
const
|
|
49534
|
+
const checkCommand = normalizeCheckCommandOption(check);
|
|
48830
49535
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
48831
49536
|
isAgentRequired: !dryRun,
|
|
48832
49537
|
});
|
|
@@ -48850,7 +49555,7 @@
|
|
|
48850
49555
|
model: runnerOptions.model,
|
|
48851
49556
|
agent,
|
|
48852
49557
|
context,
|
|
48853
|
-
|
|
49558
|
+
checkCommand,
|
|
48854
49559
|
preserveLogs,
|
|
48855
49560
|
noUi: runnerOptions.noUi,
|
|
48856
49561
|
thinkingLevel: runnerOptions.thinkingLevel,
|
|
@@ -48867,13 +49572,17 @@
|
|
|
48867
49572
|
};
|
|
48868
49573
|
validateCoderRunOptions(runOptions);
|
|
48869
49574
|
const workspace = await $preflightWorkspaceRepository({
|
|
49575
|
+
...projectOptions,
|
|
48870
49576
|
policy: dryRun ? 'read-only' : 'mutate',
|
|
48871
49577
|
...questionsOptions,
|
|
48872
49578
|
});
|
|
49579
|
+
const { resolveCoderProjectContext } = await Promise.resolve().then(function () { return resolveCoderProjectContext$1; });
|
|
49580
|
+
const projectContext = await resolveCoderProjectContext({
|
|
49581
|
+
projectPath: workspace.projectPath,
|
|
49582
|
+
agent,
|
|
49583
|
+
context,
|
|
49584
|
+
});
|
|
48873
49585
|
if (!dryRun) {
|
|
48874
|
-
// Reject missing or unreadable Books before offering installations or project configuration writes.
|
|
48875
|
-
const { resolveCoderAgentBook } = await Promise.resolve().then(function () { return resolveCoderAgent$1; });
|
|
48876
|
-
await resolveCoderAgentBook(agent, workspace.projectPath, { defaultRole: 'developer' });
|
|
48877
49586
|
// Check disk space before installations and repository writes; previews require no setup.
|
|
48878
49587
|
await $assertSufficientFreeDiskSpace(workspace.projectPath);
|
|
48879
49588
|
await $ensureHarnessInstallations([runnerOptions.agentName], questionsOptions);
|
|
@@ -48882,7 +49591,7 @@
|
|
|
48882
49591
|
// Note: Import dynamically to avoid loading heavy dependencies until needed
|
|
48883
49592
|
const { runCodexPromptsServer } = await Promise.resolve().then(function () { return runCodexPromptsServer$1; });
|
|
48884
49593
|
try {
|
|
48885
|
-
await runCodexPromptsServer({ ...runOptions, workspace });
|
|
49594
|
+
await runCodexPromptsServer({ ...runOptions, workspace, projectContext });
|
|
48886
49595
|
}
|
|
48887
49596
|
catch (error) {
|
|
48888
49597
|
assertsError(error);
|
|
@@ -48908,23 +49617,6 @@
|
|
|
48908
49617
|
}
|
|
48909
49618
|
return port;
|
|
48910
49619
|
}
|
|
48911
|
-
/**
|
|
48912
|
-
* Joins one Commander option that may be parsed either as a single string or a variadic token array.
|
|
48913
|
-
*
|
|
48914
|
-
* @private internal utility of `coder server` command
|
|
48915
|
-
*/
|
|
48916
|
-
function normalizeCommandOptionValue(value) {
|
|
48917
|
-
if (value === undefined) {
|
|
48918
|
-
return undefined;
|
|
48919
|
-
}
|
|
48920
|
-
const parts = Array.isArray(value) ? value : [value];
|
|
48921
|
-
const normalizedValue = parts
|
|
48922
|
-
.map((part) => part.trim())
|
|
48923
|
-
.filter(Boolean)
|
|
48924
|
-
.join(' ')
|
|
48925
|
-
.trim();
|
|
48926
|
-
return normalizedValue === '' ? undefined : normalizedValue;
|
|
48927
|
-
}
|
|
48928
49620
|
// Note: [🟡] Code for CLI command [server](src/cli/cli-commands/coder/server.ts) should never be published outside of `@promptbook/cli`
|
|
48929
49621
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
48930
49622
|
|
|
@@ -49002,9 +49694,11 @@
|
|
|
49002
49694
|
addCoderGitSyncOptions(command);
|
|
49003
49695
|
addWorkspaceRepositoryOptions(command);
|
|
49004
49696
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
49697
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
49005
49698
|
const { order, ignore } = cliOptions;
|
|
49006
49699
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
49007
49700
|
const workspace = await $preflightWorkspaceRepository({
|
|
49701
|
+
...projectOptions,
|
|
49008
49702
|
policy: 'mutate',
|
|
49009
49703
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
49010
49704
|
});
|
|
@@ -49040,7 +49734,7 @@
|
|
|
49040
49734
|
* The coder command provides utilities for automated coding:
|
|
49041
49735
|
* - init: Initialize coder configuration in current project
|
|
49042
49736
|
* - add: Add one ready-to-run prompt file to the queue
|
|
49043
|
-
* - plan: Discuss features with
|
|
49737
|
+
* - plan: Discuss features with Developer and author reviewed PRDs
|
|
49044
49738
|
* - generate-boilerplates: Generate prompt boilerplate files
|
|
49045
49739
|
* - find-refactor-candidates: Find files that need refactoring
|
|
49046
49740
|
* - list: List ready prompts in priority order without running them
|
|
@@ -49061,7 +49755,7 @@
|
|
|
49061
49755
|
Subcommands:
|
|
49062
49756
|
- init: Initialize coder configuration in current project
|
|
49063
49757
|
- add: Add one ready-to-run prompt file to the queue
|
|
49064
|
-
- plan: Discuss features with
|
|
49758
|
+
- plan: Discuss features with Developer and author reviewed PRDs
|
|
49065
49759
|
- generate-boilerplates: Generate prompt boilerplate files
|
|
49066
49760
|
- find-refactor-candidates: Find files that need refactoring
|
|
49067
49761
|
- find-unwritten: List prompt sections that still need to be authored
|
|
@@ -72182,12 +72876,21 @@
|
|
|
72182
72876
|
}
|
|
72183
72877
|
const textPath = path.resolve(options.currentWorkingDirectory, normalizedTextReference);
|
|
72184
72878
|
const textPathStats = await promises.stat(textPath).catch((error) => {
|
|
72185
|
-
if (error.code === 'ENOENT') {
|
|
72879
|
+
if (error.code === 'ENOENT' || error.code === 'ENOTDIR') {
|
|
72186
72880
|
return undefined;
|
|
72187
72881
|
}
|
|
72188
|
-
|
|
72882
|
+
if (['ENAMETOOLONG', 'EINVAL', 'ERR_INVALID_ARG_VALUE'].includes(error.code || '') && !isContextFileReference(normalizedTextReference)) {
|
|
72883
|
+
return undefined;
|
|
72884
|
+
}
|
|
72885
|
+
throw contextReadError(options, textPath, error);
|
|
72189
72886
|
});
|
|
72190
72887
|
if (!textPathStats) {
|
|
72888
|
+
if (options.isMissingFileAnError && isContextFileReference(normalizedTextReference)) {
|
|
72889
|
+
throw new NotFoundError(spaceTrim(`
|
|
72890
|
+
${options.contextLabel} file \`${textPath}\` does not exist.
|
|
72891
|
+
Correct the file path in \`${options.optionName}\` or pass inline instructions.
|
|
72892
|
+
`));
|
|
72893
|
+
}
|
|
72191
72894
|
return normalizedTextReference;
|
|
72192
72895
|
}
|
|
72193
72896
|
if (!textPathStats.isFile()) {
|
|
@@ -72197,7 +72900,55 @@
|
|
|
72197
72900
|
Pass a file path or inline text in \`${options.optionName}\`.
|
|
72198
72901
|
`));
|
|
72199
72902
|
}
|
|
72200
|
-
return promises.readFile(textPath, 'utf-8')
|
|
72903
|
+
return promises.readFile(textPath, 'utf-8').catch((error) => {
|
|
72904
|
+
throw contextReadError(options, textPath, error);
|
|
72905
|
+
});
|
|
72906
|
+
}
|
|
72907
|
+
/** Distinguishes explicit file spellings from ordinary inline instructions, including native Windows paths. */
|
|
72908
|
+
function isContextFileReference(reference) {
|
|
72909
|
+
return path.isAbsolute(reference) || /^(?:\.{1,2}[/\\]|[a-z]:[/\\]|\\\\)/iu.test(reference) ||
|
|
72910
|
+
(!/[\r\n]/u.test(reference) && /\.(?:md|markdown|txt|book|json|ya?ml)$/iu.test(reference)) ||
|
|
72911
|
+
(!/\s/u.test(reference) && /[/\\]/u.test(reference) && !/^[a-z]+:\/\//iu.test(reference));
|
|
72912
|
+
}
|
|
72913
|
+
/** Adds the selected path and recovery guidance to filesystem failures. */
|
|
72914
|
+
function contextReadError(options, path, error) {
|
|
72915
|
+
return new NotAllowed(spaceTrim(`
|
|
72916
|
+
Cannot read ${options.contextLabel.toLowerCase()} file \`${path}\`: ${error.message}
|
|
72917
|
+
Check file permissions and the path in \`${options.optionName}\`.
|
|
72918
|
+
`));
|
|
72919
|
+
}
|
|
72920
|
+
|
|
72921
|
+
/**
|
|
72922
|
+
* Resolves project AGENTS.md on omission; explicit text, files and intentional empty values replace it.
|
|
72923
|
+
*/
|
|
72924
|
+
async function resolveCoderContext(contextReference, currentWorkingDirectory) {
|
|
72925
|
+
if (contextReference === undefined) {
|
|
72926
|
+
const contextPath = path.join(currentWorkingDirectory, AGENTS_FILE_PATH);
|
|
72927
|
+
try {
|
|
72928
|
+
return await promises.readFile(contextPath, 'utf-8');
|
|
72929
|
+
}
|
|
72930
|
+
catch (error) {
|
|
72931
|
+
if (error.code === 'ENOENT') {
|
|
72932
|
+
// A broken symlink is an existing, unreadable default, not an absent optional file.
|
|
72933
|
+
const isMissing = await promises.lstat(contextPath).then(() => false, (failure) => failure.code === 'ENOENT');
|
|
72934
|
+
if (isMissing) {
|
|
72935
|
+
console.warn(`No additional context: \`${contextPath}\` is missing.`);
|
|
72936
|
+
return undefined;
|
|
72937
|
+
}
|
|
72938
|
+
}
|
|
72939
|
+
throw new NotAllowed(spaceTrim(`
|
|
72940
|
+
Cannot read default context file \`${contextPath}\`: ${error instanceof Error ? error.message : String(error)}
|
|
72941
|
+
Check its permissions, or replace it with \`--context\` (an empty value disables additional context).
|
|
72942
|
+
`));
|
|
72943
|
+
}
|
|
72944
|
+
}
|
|
72945
|
+
return resolveInlineOrFileText({
|
|
72946
|
+
textReference: contextReference,
|
|
72947
|
+
currentWorkingDirectory,
|
|
72948
|
+
contextLabel: 'Coding context',
|
|
72949
|
+
optionName: '--context',
|
|
72950
|
+
isMissingFileAnError: true,
|
|
72951
|
+
});
|
|
72201
72952
|
}
|
|
72202
72953
|
|
|
72203
72954
|
/**
|
|
@@ -72276,11 +73027,7 @@
|
|
|
72276
73027
|
.toLowerCase()
|
|
72277
73028
|
.replace(/[^a-z0-9._-]+/gu, '-')
|
|
72278
73029
|
.replace(/^[._-]+|[._-]+$/gu, '');
|
|
72279
|
-
const sessionName = [
|
|
72280
|
-
safeAgentName || 'agent',
|
|
72281
|
-
Date.now().toString(36),
|
|
72282
|
-
$randomToken(4),
|
|
72283
|
-
].join('-');
|
|
73030
|
+
const sessionName = [safeAgentName || 'agent', Date.now().toString(36), $randomToken(4)].join('-');
|
|
72284
73031
|
return resolvePromptbookTemporaryPath(options.currentWorkingDirectory, AGENT_CHAT_TEMPORARY_DIRECTORY_NAME, AGENT_CHAT_SESSIONS_DIRECTORY_NAME, sessionName);
|
|
72285
73032
|
}
|
|
72286
73033
|
/**
|
|
@@ -72335,7 +73082,7 @@
|
|
|
72335
73082
|
return {
|
|
72336
73083
|
dryRun: false,
|
|
72337
73084
|
context: undefined,
|
|
72338
|
-
|
|
73085
|
+
checkCommand: undefined,
|
|
72339
73086
|
preserveLogs: false,
|
|
72340
73087
|
noUi: options.noUi,
|
|
72341
73088
|
thinkingLevel: options.thinkingLevel,
|
|
@@ -72401,12 +73148,7 @@
|
|
|
72401
73148
|
*/
|
|
72402
73149
|
async function runAgentChat(options) {
|
|
72403
73150
|
const currentWorkingDirectory = options.currentWorkingDirectory || process.cwd();
|
|
72404
|
-
const context = await
|
|
72405
|
-
textReference: options.context,
|
|
72406
|
-
currentWorkingDirectory,
|
|
72407
|
-
contextLabel: 'Agent context',
|
|
72408
|
-
optionName: '--context',
|
|
72409
|
-
});
|
|
73151
|
+
const context = await resolveCoderContext(options.context, currentWorkingDirectory);
|
|
72410
73152
|
const workspacePath = createAgentChatWorkspacePath({
|
|
72411
73153
|
currentWorkingDirectory,
|
|
72412
73154
|
agentPath: options.agentPath,
|
|
@@ -72469,12 +73211,7 @@
|
|
|
72469
73211
|
throw new NotAllowed('Pass a non-empty user message in `--message`.');
|
|
72470
73212
|
}
|
|
72471
73213
|
const currentWorkingDirectory = options.currentWorkingDirectory || process.cwd();
|
|
72472
|
-
const context = await
|
|
72473
|
-
textReference: options.context,
|
|
72474
|
-
currentWorkingDirectory,
|
|
72475
|
-
contextLabel: 'Agent context',
|
|
72476
|
-
optionName: '--context',
|
|
72477
|
-
});
|
|
73214
|
+
const context = await resolveCoderContext(options.context, currentWorkingDirectory);
|
|
72478
73215
|
const result = await executeAgentChatTurn({
|
|
72479
73216
|
...options,
|
|
72480
73217
|
currentWorkingDirectory,
|
|
@@ -72560,13 +73297,13 @@
|
|
|
72560
73297
|
* Watches the queued message directory and answers messages one by one.
|
|
72561
73298
|
*/
|
|
72562
73299
|
async function runAgentMessages(options, controls = {}) {
|
|
72563
|
-
var _a, _b;
|
|
73300
|
+
var _a, _b, _c;
|
|
72564
73301
|
validateAgentRunOptions(options);
|
|
72565
73302
|
validateAgentWatchOptions('ptbk agent-folder run-agent', options);
|
|
72566
|
-
const projectPath = process.cwd();
|
|
73303
|
+
const projectPath = (_a = options.projectPath) !== null && _a !== void 0 ? _a : process.cwd();
|
|
72567
73304
|
let autoPullTimestamp = options.autoPull ? Date.now() : undefined;
|
|
72568
73305
|
const shouldContinue = controls.shouldContinue || (() => just(true));
|
|
72569
|
-
const queuePollIntervalMs = (
|
|
73306
|
+
const queuePollIntervalMs = (_b = controls.queuePollIntervalMs) !== null && _b !== void 0 ? _b : AGENT_QUEUE_POLL_INTERVAL_MS;
|
|
72570
73307
|
let isWatchSessionInitialized = false;
|
|
72571
73308
|
let uiHandle;
|
|
72572
73309
|
const messageFailureTracker = new AgentMessageFailureTracker({
|
|
@@ -72583,7 +73320,7 @@
|
|
|
72583
73320
|
}
|
|
72584
73321
|
}
|
|
72585
73322
|
const result = await tickAgentMessages(options, { isQuietWhenIdle: true, uiHandle });
|
|
72586
|
-
autoPullTimestamp = (
|
|
73323
|
+
autoPullTimestamp = (_c = result.autoPullTimestamp) !== null && _c !== void 0 ? _c : autoPullTimestamp;
|
|
72587
73324
|
if (result.isMessageProcessed) {
|
|
72588
73325
|
messageFailureTracker.clearMessageFailure(projectPath, result.queuedMessage);
|
|
72589
73326
|
continue;
|
|
@@ -78436,8 +79173,8 @@
|
|
|
78436
79173
|
/**
|
|
78437
79174
|
* Builds a display label using the prompt line number for easier navigation.
|
|
78438
79175
|
*/
|
|
78439
|
-
function buildPromptLabelForDisplay(file, section) {
|
|
78440
|
-
return `${path.relative(
|
|
79176
|
+
function buildPromptLabelForDisplay(file, section, projectPath = process.cwd()) {
|
|
79177
|
+
return `${path.relative(projectPath, file.path).replace(/\\/g, '/')}#${section.startLine + 1}`;
|
|
78441
79178
|
}
|
|
78442
79179
|
|
|
78443
79180
|
/**
|
|
@@ -78452,11 +79189,11 @@
|
|
|
78452
79189
|
/**
|
|
78453
79190
|
* Prints the list of prompts that still need to be written.
|
|
78454
79191
|
*/
|
|
78455
|
-
function printPromptsToBeWritten(files, priorityFilter = {}) {
|
|
79192
|
+
function printPromptsToBeWritten(files, priorityFilter = {}, projectPath) {
|
|
78456
79193
|
const promptsToWrite = listPromptsToBeWritten(files, priorityFilter);
|
|
78457
79194
|
let i = 0;
|
|
78458
79195
|
for (const { file, section } of promptsToWrite) {
|
|
78459
|
-
const label = buildPromptLabelForDisplay(file, section);
|
|
79196
|
+
const label = buildPromptLabelForDisplay(file, section, projectPath);
|
|
78460
79197
|
const summary = buildPromptSummary(file, section);
|
|
78461
79198
|
console.info(` ${++i}) ${label}: ${summary}`);
|
|
78462
79199
|
}
|
|
@@ -78526,7 +79263,7 @@
|
|
|
78526
79263
|
}
|
|
78527
79264
|
else {
|
|
78528
79265
|
console.info(colors__default["default"].yellow(`Found ${unwrittenPrompts.length} prompt(s) that need to be written:`));
|
|
78529
|
-
printPromptsToBeWritten(promptFiles, priorityFilter);
|
|
79266
|
+
printPromptsToBeWritten(promptFiles, priorityFilter, options.projectPath);
|
|
78530
79267
|
}
|
|
78531
79268
|
return unwrittenPrompts.length;
|
|
78532
79269
|
}
|
|
@@ -79370,9 +80107,9 @@
|
|
|
79370
80107
|
/**
|
|
79371
80108
|
* Lists upcoming tasks that are ready to run (no authoring placeholders).
|
|
79372
80109
|
*/
|
|
79373
|
-
function listUpcomingTasks(files, priorityFilter = {}, promptRunnerIdentity) {
|
|
80110
|
+
function listUpcomingTasks(files, priorityFilter = {}, promptRunnerIdentity, projectPath) {
|
|
79374
80111
|
return listRunnablePrompts(files, priorityFilter, promptRunnerIdentity).map(({ file, section }) => ({
|
|
79375
|
-
label: buildPromptLabelForDisplay(file, section),
|
|
80112
|
+
label: buildPromptLabelForDisplay(file, section, projectPath),
|
|
79376
80113
|
summary: buildPromptSummary(file, section),
|
|
79377
80114
|
priority: section.priority,
|
|
79378
80115
|
}));
|
|
@@ -79427,7 +80164,7 @@
|
|
|
79427
80164
|
const promptFiles = await loadPromptFiles(path.join((_a = options.projectPath) !== null && _a !== void 0 ? _a : process.cwd(), 'prompts'), {
|
|
79428
80165
|
isMissingDirectoryAllowed: true,
|
|
79429
80166
|
});
|
|
79430
|
-
const upcomingTasks = listUpcomingTasks(promptFiles, priorityFilter, options.promptRunnerIdentity);
|
|
80167
|
+
const upcomingTasks = listUpcomingTasks(promptFiles, priorityFilter, options.promptRunnerIdentity, options.projectPath);
|
|
79431
80168
|
printUpcomingTasks(upcomingTasks);
|
|
79432
80169
|
return upcomingTasks.length;
|
|
79433
80170
|
}
|
|
@@ -79807,6 +80544,24 @@
|
|
|
79807
80544
|
createPlanningTerminal: createPlanningTerminal
|
|
79808
80545
|
});
|
|
79809
80546
|
|
|
80547
|
+
/**
|
|
80548
|
+
* Resolves single-agent execution/authoring defaults without compiling Books or creating artifacts.
|
|
80549
|
+
* Execution previews use the same identity and routing. Utilities and all-agent discovery resolve
|
|
80550
|
+
* only the project directory and must not call this service to manufacture a primary-agent filter.
|
|
80551
|
+
*/
|
|
80552
|
+
async function resolveCoderProjectContext(options) {
|
|
80553
|
+
const agentBook = await resolveCoderAgentBook(options.agent, options.projectPath, {
|
|
80554
|
+
defaultRole: DEFAULT_CODER_AGENT_ROLE,
|
|
80555
|
+
});
|
|
80556
|
+
const context = await resolveCoderContext(options.context, options.projectPath);
|
|
80557
|
+
return { projectPath: options.projectPath, agentBook, context };
|
|
80558
|
+
}
|
|
80559
|
+
|
|
80560
|
+
var resolveCoderProjectContext$1 = /*#__PURE__*/Object.freeze({
|
|
80561
|
+
__proto__: null,
|
|
80562
|
+
resolveCoderProjectContext: resolveCoderProjectContext
|
|
80563
|
+
});
|
|
80564
|
+
|
|
79810
80565
|
/** Maximum question length accepted by both command and planning tools. */
|
|
79811
80566
|
const MAX_MESSAGE_LENGTH = 32000;
|
|
79812
80567
|
/** Maximum context length accepted by both command and planning tools. */
|
|
@@ -80025,6 +80780,19 @@
|
|
|
80025
80780
|
}
|
|
80026
80781
|
// Note: [💞] Runtime contract types accompany their implementation.
|
|
80027
80782
|
|
|
80783
|
+
/**
|
|
80784
|
+
* Rebinds an absolute reference inside a project/repository to its worktree copy. Relative references
|
|
80785
|
+
* already resolve against the execution project; explicit references outside that checkout remain explicit.
|
|
80786
|
+
*/
|
|
80787
|
+
function mapProjectReferenceToWorktree(reference, originalProjectPath, worktreeProjectPath) {
|
|
80788
|
+
if (reference === undefined || !path.isAbsolute(reference.trim()))
|
|
80789
|
+
return reference;
|
|
80790
|
+
const relativePath = path.relative(originalProjectPath, reference.trim());
|
|
80791
|
+
if (path.isAbsolute(relativePath) || relativePath === '..' || /^\.\.[/\\]/u.test(relativePath))
|
|
80792
|
+
return reference;
|
|
80793
|
+
return path.join(worktreeProjectPath, relativePath);
|
|
80794
|
+
}
|
|
80795
|
+
|
|
80028
80796
|
/** Limits apply before JSON parsing, even when a client bypasses the generated command. */
|
|
80029
80797
|
const MAX_REQUEST_BYTES = 131072;
|
|
80030
80798
|
/** Each invocation receives an independent 256-bit bearer credential. */
|
|
@@ -80211,7 +80979,7 @@
|
|
|
80211
80979
|
* Adds a scoped consultation transport around an existing adapter. Both primary and advisers keep exactly
|
|
80212
80980
|
* that adapter's permissions and authentication. Only the enclosing Coder round owns tests, queues and Git operations.
|
|
80213
80981
|
*/
|
|
80214
|
-
function createCoderTeamPromptRunner(runner, agentBookReference) {
|
|
80982
|
+
function createCoderTeamPromptRunner(runner, agentBookReference, originalProjectPath, originalRepositoryRoot = originalProjectPath) {
|
|
80215
80983
|
var _a;
|
|
80216
80984
|
return {
|
|
80217
80985
|
name: runner.name,
|
|
@@ -80227,8 +80995,11 @@
|
|
|
80227
80995
|
let runtime;
|
|
80228
80996
|
try {
|
|
80229
80997
|
// Resolve against this invocation's actual checkout, including an isolated worktree.
|
|
80230
|
-
const
|
|
80231
|
-
|
|
80998
|
+
const reference = originalProjectPath
|
|
80999
|
+
? mapProjectReferenceToWorktree(agentBookReference, originalRepositoryRoot, path.resolve(options.projectPath, path.relative(originalProjectPath, originalRepositoryRoot)))
|
|
81000
|
+
: agentBookReference;
|
|
81001
|
+
const agent = await resolveCoderAgent(reference, options.projectPath, {
|
|
81002
|
+
defaultRole: DEFAULT_CODER_AGENT_ROLE,
|
|
80232
81003
|
isInitializationAllowed: false,
|
|
80233
81004
|
signal: controller.signal,
|
|
80234
81005
|
});
|
|
@@ -81109,11 +81880,12 @@
|
|
|
81109
81880
|
* @private internal utility of `coder plan`
|
|
81110
81881
|
*/
|
|
81111
81882
|
async function runPlanningSession(options, io, harness = runPlanningHarness) {
|
|
81112
|
-
var _a, _b;
|
|
81883
|
+
var _a, _b, _c;
|
|
81113
81884
|
const projectPath = await promises.realpath(options.projectPath);
|
|
81114
81885
|
assertPlanningHarnessSupported(options.agentName);
|
|
81886
|
+
const projectContext = (_a = options.projectContext) !== null && _a !== void 0 ? _a : (await resolveCoderProjectContext({ ...options, projectPath }));
|
|
81115
81887
|
const agent = await resolveCoderAgent(options.agent, projectPath, {
|
|
81116
|
-
defaultRole:
|
|
81888
|
+
defaultRole: DEFAULT_CODER_AGENT_ROLE,
|
|
81117
81889
|
isInitializationAllowed: false,
|
|
81118
81890
|
signal: io.signal,
|
|
81119
81891
|
});
|
|
@@ -81121,9 +81893,9 @@
|
|
|
81121
81893
|
throw new NotFoundError(spaceTrim('Planning requires `prompts/`. Run `ptbk coder init` first.'));
|
|
81122
81894
|
}
|
|
81123
81895
|
if (!agent)
|
|
81124
|
-
throw new NotFoundError(spaceTrim('
|
|
81896
|
+
throw new NotFoundError(spaceTrim('Primary Book is missing. Run `ptbk coder init`.'));
|
|
81125
81897
|
resolvePlanningPath(projectPath, 'prompts');
|
|
81126
|
-
const templateOption = (
|
|
81898
|
+
const templateOption = (_b = options.template) !== null && _b !== void 0 ? _b : (fs.existsSync(path.join(projectPath, COMMON_PROMPT_TEMPLATE_FILE_PATH))
|
|
81127
81899
|
? COMMON_PROMPT_TEMPLATE_FILE_PATH
|
|
81128
81900
|
: undefined);
|
|
81129
81901
|
const template = await resolveCoderPromptTemplate({ projectPath, templateOption });
|
|
@@ -81167,7 +81939,10 @@
|
|
|
81167
81939
|
},
|
|
81168
81940
|
{ role: 'context', content: await readPlanningContext(projectPath, { kind: 'list', path: '.' }) },
|
|
81169
81941
|
];
|
|
81170
|
-
|
|
81942
|
+
if (projectContext.context !== undefined) {
|
|
81943
|
+
history.push({ role: 'context', content: projectContext.context });
|
|
81944
|
+
}
|
|
81945
|
+
for (const path$1 of ['README.md']) {
|
|
81171
81946
|
if (fs.existsSync(path.join(projectPath, path$1))) {
|
|
81172
81947
|
history.push({
|
|
81173
81948
|
role: 'context',
|
|
@@ -81184,7 +81959,7 @@
|
|
|
81184
81959
|
let pending = [];
|
|
81185
81960
|
io.write(`${agent.agentName}: Discuss features and review PRD proposals. /save applies the preview; /draft saves unresolved drafts; /discard drops it; /exit ends. Ctrl+C cancels.\n`);
|
|
81186
81961
|
while (!io.signal.aborted) {
|
|
81187
|
-
const message = (
|
|
81962
|
+
const message = (_c = (await io.readMessage())) === null || _c === void 0 ? void 0 : _c.trim();
|
|
81188
81963
|
if (message === undefined || ['/exit', 'exit', 'quit'].includes(message))
|
|
81189
81964
|
break;
|
|
81190
81965
|
if (!message)
|
|
@@ -81321,7 +82096,7 @@
|
|
|
81321
82096
|
/**
|
|
81322
82097
|
* CLI usage text for this script.
|
|
81323
82098
|
*/
|
|
81324
|
-
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--harness <harness-name>] [--model <model>] [--agent <agent-book-path>] [--context <context-or-file>] [--
|
|
82099
|
+
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--harness <harness-name>] [--model <model>] [--agent <agent-book-path>] [--context <context-or-file>] [--check <check-command...>] [--check-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] [--git-changes <fail|ignore|continue>] [--no-normalize-line-endings] [--auto-push] [--auto-pull]';
|
|
81325
82100
|
/**
|
|
81326
82101
|
* Top-level flags supported by this command.
|
|
81327
82102
|
*/
|
|
@@ -81331,8 +82106,8 @@
|
|
|
81331
82106
|
'--model',
|
|
81332
82107
|
'--agent',
|
|
81333
82108
|
'--context',
|
|
81334
|
-
'--
|
|
81335
|
-
'--
|
|
82109
|
+
'--check',
|
|
82110
|
+
'--check-before',
|
|
81336
82111
|
'--preserve-logs',
|
|
81337
82112
|
'--isolate',
|
|
81338
82113
|
'--no-ui',
|
|
@@ -81358,6 +82133,15 @@
|
|
|
81358
82133
|
* Parses CLI arguments into runner options.
|
|
81359
82134
|
*/
|
|
81360
82135
|
function parseRunOptions(args) {
|
|
82136
|
+
args = args.flatMap((argument) => {
|
|
82137
|
+
const match = argument.match(/^(--check(?:-before)?)=([\s\S]*)$/u);
|
|
82138
|
+
return match ? [match[1], match[2]] : [argument];
|
|
82139
|
+
});
|
|
82140
|
+
for (const [legacyFlag, replacementFlag] of LEGACY_CODER_CHECK_OPTIONS) {
|
|
82141
|
+
if (args.some((argument) => argument === legacyFlag || argument.startsWith(`${legacyFlag}=`))) {
|
|
82142
|
+
exitWithUsageError(formatLegacyCoderCheckOptionError(legacyFlag, replacementFlag));
|
|
82143
|
+
}
|
|
82144
|
+
}
|
|
81361
82145
|
let agentName = undefined;
|
|
81362
82146
|
const dryRun = args.includes('--dry-run');
|
|
81363
82147
|
const harnessValue = readOptionValue(args, '--harness');
|
|
@@ -81373,10 +82157,10 @@
|
|
|
81373
82157
|
exitWithUsageError('Pass a non-empty Book path after `--agent`, or omit it to use `agents/developer.book`.');
|
|
81374
82158
|
}
|
|
81375
82159
|
const context = readOptionValue(args, '--context');
|
|
81376
|
-
const
|
|
81377
|
-
const
|
|
81378
|
-
const
|
|
81379
|
-
const
|
|
82160
|
+
const hasCheckCommandFlag = args.includes('--check');
|
|
82161
|
+
const checkCommand = readVariadicOptionValue(args, '--check');
|
|
82162
|
+
const hasCheckBeforeFlag = args.includes('--check-before');
|
|
82163
|
+
const checkBefore = parseCheckBeforeOption(readOptionValue(args, '--check-before'), hasCheckBeforeFlag);
|
|
81380
82164
|
const preserveLogs = args.includes('--preserve-logs');
|
|
81381
82165
|
const isIsolated = args.includes('--isolate');
|
|
81382
82166
|
const noUi = args.includes('--no-ui');
|
|
@@ -81414,8 +82198,8 @@
|
|
|
81414
82198
|
const waitBetweenPrompts = parseWaitOption(args, '--wait-between-prompts', 0);
|
|
81415
82199
|
const waitAfterError = parseWaitOption(args, '--wait-after-error', DEFAULT_WAIT_AFTER_ERROR_MS);
|
|
81416
82200
|
let thinkingLevel;
|
|
81417
|
-
if (
|
|
81418
|
-
exitWithUsageError('Missing value for --
|
|
82201
|
+
if (hasCheckCommandFlag && checkCommand === undefined) {
|
|
82202
|
+
exitWithUsageError('Missing value for --check. Use a shell command such as `npm run check` and quote it when it contains top-level CLI flags.');
|
|
81419
82203
|
}
|
|
81420
82204
|
if (hasThinkingLevelFlag && thinkingLevelValue === undefined) {
|
|
81421
82205
|
exitWithUsageError(`Missing value for --thinking-level. Use one of: ${THINKING_LEVEL_VALUES.join(', ')}.`);
|
|
@@ -81450,8 +82234,8 @@
|
|
|
81450
82234
|
model,
|
|
81451
82235
|
agent,
|
|
81452
82236
|
context,
|
|
81453
|
-
|
|
81454
|
-
|
|
82237
|
+
checkCommand: resolveCoderCheckCommand(checkCommand, checkBefore),
|
|
82238
|
+
checkBefore,
|
|
81455
82239
|
thinkingLevel,
|
|
81456
82240
|
priority: minimumPriority !== null && minimumPriority !== void 0 ? minimumPriority : 0,
|
|
81457
82241
|
minimumPriority,
|
|
@@ -81463,15 +82247,15 @@
|
|
|
81463
82247
|
/**
|
|
81464
82248
|
* Parses and validates the optional pre-coding verification mode.
|
|
81465
82249
|
*/
|
|
81466
|
-
function
|
|
82250
|
+
function parseCheckBeforeOption(value, hasCheckBeforeFlag) {
|
|
81467
82251
|
if (value === undefined) {
|
|
81468
|
-
if (
|
|
81469
|
-
exitWithUsageError(`Missing value for --
|
|
82252
|
+
if (hasCheckBeforeFlag) {
|
|
82253
|
+
exitWithUsageError(`Missing value for --check-before. Use one of: ${CHECK_BEFORE_MODE_VALUES.join(', ')}.`);
|
|
81470
82254
|
}
|
|
81471
82255
|
return 'no';
|
|
81472
82256
|
}
|
|
81473
|
-
if (!
|
|
81474
|
-
exitWithUsageError(`Invalid value for --
|
|
82257
|
+
if (!isCheckBeforeMode(value)) {
|
|
82258
|
+
exitWithUsageError(`Invalid value for --check-before: "${value}". Use one of: ${CHECK_BEFORE_MODE_VALUES.join(', ')}.`);
|
|
81475
82259
|
}
|
|
81476
82260
|
return value;
|
|
81477
82261
|
}
|
|
@@ -81532,8 +82316,14 @@
|
|
|
81532
82316
|
}
|
|
81533
82317
|
valueParts.push(valuePart);
|
|
81534
82318
|
}
|
|
81535
|
-
|
|
81536
|
-
|
|
82319
|
+
if (valueParts.length === 0)
|
|
82320
|
+
return undefined;
|
|
82321
|
+
try {
|
|
82322
|
+
return normalizeCheckCommandOption(valueParts);
|
|
82323
|
+
}
|
|
82324
|
+
catch (error) {
|
|
82325
|
+
exitWithUsageError(error instanceof Error ? error.message : String(error));
|
|
82326
|
+
}
|
|
81537
82327
|
}
|
|
81538
82328
|
/**
|
|
81539
82329
|
* Parses and validates one priority boundary.
|
|
@@ -81975,18 +82765,6 @@
|
|
|
81975
82765
|
});
|
|
81976
82766
|
}
|
|
81977
82767
|
|
|
81978
|
-
/**
|
|
81979
|
-
* Resolves optional coding context provided inline or via a file path.
|
|
81980
|
-
*/
|
|
81981
|
-
async function resolveCoderContext(contextReference, currentWorkingDirectory) {
|
|
81982
|
-
return resolveInlineOrFileText({
|
|
81983
|
-
textReference: contextReference,
|
|
81984
|
-
currentWorkingDirectory,
|
|
81985
|
-
contextLabel: 'Coding context',
|
|
81986
|
-
optionName: '--context',
|
|
81987
|
-
});
|
|
81988
|
-
}
|
|
81989
|
-
|
|
81990
82768
|
/**
|
|
81991
82769
|
* Listens for the terminal control keys while the plain console output is used.
|
|
81992
82770
|
*
|
|
@@ -83581,7 +84359,7 @@
|
|
|
83581
84359
|
*/
|
|
83582
84360
|
const CODER_RUN_STEP_LABELS = {
|
|
83583
84361
|
implementation: 'Implementation',
|
|
83584
|
-
|
|
84362
|
+
checking: 'Checking',
|
|
83585
84363
|
fixing: 'Fixing',
|
|
83586
84364
|
};
|
|
83587
84365
|
/**
|
|
@@ -83592,16 +84370,16 @@
|
|
|
83592
84370
|
* Formats the per-step usage breakdown recorded for one prompt.
|
|
83593
84371
|
*
|
|
83594
84372
|
* Produces a `; `-separated summary such as
|
|
83595
|
-
* `Implementation $8.01 6 hours;
|
|
84373
|
+
* `Implementation $8.01 6 hours; Checking 1 hour; Fixing $3.14 2 hours` where each coding step carries its
|
|
83596
84374
|
* price and duration and each verification step carries only its duration.
|
|
83597
84375
|
*
|
|
83598
84376
|
* @param steps - Steps which have already finished
|
|
83599
|
-
* @param inProgressStepKind - Step which has started but has not finished yet, appended as `
|
|
84377
|
+
* @param inProgressStepKind - Step which has started but has not finished yet, appended as `Checking in progress`
|
|
83600
84378
|
*/
|
|
83601
84379
|
function formatCoderRunSteps(steps, inProgressStepKind) {
|
|
83602
84380
|
const formattedSteps = steps.map(formatCoderRunStep);
|
|
83603
84381
|
if (inProgressStepKind !== undefined) {
|
|
83604
|
-
formattedSteps.push(`${CODER_RUN_STEP_LABELS[inProgressStepKind]} ${IN_PROGRESS_STEP_SUFFIX}`);
|
|
84382
|
+
formattedSteps.push(`${CODER_RUN_STEP_LABELS[decodeCoderRunStepKind(inProgressStepKind)]} ${IN_PROGRESS_STEP_SUFFIX}`);
|
|
83605
84383
|
}
|
|
83606
84384
|
return formattedSteps.join('; ');
|
|
83607
84385
|
}
|
|
@@ -83609,7 +84387,7 @@
|
|
|
83609
84387
|
* Formats one coder run step as `Label $price duration`, omitting the price for steps without model usage.
|
|
83610
84388
|
*/
|
|
83611
84389
|
function formatCoderRunStep(step) {
|
|
83612
|
-
const label = CODER_RUN_STEP_LABELS[step.kind];
|
|
84390
|
+
const label = CODER_RUN_STEP_LABELS[decodeCoderRunStepKind(step.kind)];
|
|
83613
84391
|
const durationString = moment__default["default"].duration(step.durationMs).humanize();
|
|
83614
84392
|
const priceString = step.usage === null ? undefined : formatUsagePrice(step.usage);
|
|
83615
84393
|
if (priceString === undefined) {
|
|
@@ -83617,6 +84395,10 @@
|
|
|
83617
84395
|
}
|
|
83618
84396
|
return `${label} ${priceString} ${durationString}`;
|
|
83619
84397
|
}
|
|
84398
|
+
/** Decodes the old aggregate step name at the display boundary; new execution only records checking. */
|
|
84399
|
+
function decodeCoderRunStepKind(kind) {
|
|
84400
|
+
return kind === 'testing' ? 'checking' : kind;
|
|
84401
|
+
}
|
|
83620
84402
|
|
|
83621
84403
|
/**
|
|
83622
84404
|
* Formats optional attempt metadata stored in prompt status lines.
|
|
@@ -83957,13 +84739,13 @@
|
|
|
83957
84739
|
`- **Runner:** ${runnerSignature}${loginMethodSuffix}`,
|
|
83958
84740
|
`- **Attempts:** ${options.attemptCount}`,
|
|
83959
84741
|
...buildPromptRunTraceStepsLines(outcome),
|
|
83960
|
-
...
|
|
84742
|
+
...buildPromptRunTraceCheckCommandLines(options.checkCommand),
|
|
83961
84743
|
`- **Started:** ${options.startedDate.toISOString()}`,
|
|
83962
84744
|
`- **Finished:** ${options.finishedDate.toISOString()}`,
|
|
83963
84745
|
`- **Duration:** ${moment__default["default"].duration(options.finishedDate.diff(options.startedDate)).humanize()}`,
|
|
83964
84746
|
];
|
|
83965
84747
|
return _spaceTrim.spaceTrim((block) => `
|
|
83966
|
-
# Run trace of \`${buildPromptLabelForDisplay(file, section)}\`
|
|
84748
|
+
# Run trace of \`${buildPromptLabelForDisplay(file, section, options.projectPath)}\`
|
|
83967
84749
|
|
|
83968
84750
|
${block(detailLines.join('\n'))}
|
|
83969
84751
|
`);
|
|
@@ -83996,11 +84778,11 @@
|
|
|
83996
84778
|
/**
|
|
83997
84779
|
* Renders the verification command of the round, omitted when the round ran without one.
|
|
83998
84780
|
*/
|
|
83999
|
-
function
|
|
84000
|
-
if (!
|
|
84781
|
+
function buildPromptRunTraceCheckCommandLines(checkCommand) {
|
|
84782
|
+
if (!checkCommand) {
|
|
84001
84783
|
return [];
|
|
84002
84784
|
}
|
|
84003
|
-
return [`- **
|
|
84785
|
+
return [`- **Check command:** \`${checkCommand}\``];
|
|
84004
84786
|
}
|
|
84005
84787
|
/**
|
|
84006
84788
|
* Renders the failure details of a failed round, omitted for a successful one.
|
|
@@ -84087,9 +84869,9 @@
|
|
|
84087
84869
|
*
|
|
84088
84870
|
* @private function of runCodexPrompts
|
|
84089
84871
|
*/
|
|
84090
|
-
async function runPromptRound({ options, runner, runnerMetadata, nextPrompt, promptLabel, resolvedCoderContext, resolvedAgentSystemMessage, isRichUiEnabled, progressDisplay, uiHandle, waitForRequestedPause, projectPath, }) {
|
|
84091
|
-
var _a, _b;
|
|
84092
|
-
const roundProjectPath = (_b = projectPath !== null && projectPath !== void 0 ? projectPath : (_a = options.workspace) === null || _a === void 0 ? void 0 : _a.projectPath) !== null && _b !== void 0 ? _b : process.cwd();
|
|
84872
|
+
async function runPromptRound({ options, runner, runnerMetadata, nextPrompt, promptLabel, resolvedCoderContext, resolvedAgentSystemMessage, isRichUiEnabled, progressDisplay, uiHandle, waitForRequestedPause, projectPath, artifactsProjectPath, }) {
|
|
84873
|
+
var _a, _b, _c;
|
|
84874
|
+
const roundProjectPath = (_c = (_b = projectPath !== null && projectPath !== void 0 ? projectPath : (_a = options.workspace) === null || _a === void 0 ? void 0 : _a.projectPath) !== null && _b !== void 0 ? _b : options.projectPath) !== null && _c !== void 0 ? _c : process.cwd();
|
|
84093
84875
|
const commitMessage = buildCommitMessage(nextPrompt.file, nextPrompt.section);
|
|
84094
84876
|
const taskPrompt = buildCodexPrompt(nextPrompt.file, nextPrompt.section);
|
|
84095
84877
|
// Prepend agent system message before the task so the harness sees agent instructions first
|
|
@@ -84106,8 +84888,7 @@
|
|
|
84106
84888
|
`)
|
|
84107
84889
|
: taskPrompt;
|
|
84108
84890
|
const codexPrompt = appendCoderContext(promptWithAgent, resolvedCoderContext);
|
|
84109
|
-
|
|
84110
|
-
const scriptPath = buildScriptPath(nextPrompt.file, nextPrompt.section);
|
|
84891
|
+
const scriptPath = buildScriptPath(nextPrompt.file, nextPrompt.section, artifactsProjectPath !== null && artifactsProjectPath !== void 0 ? artifactsProjectPath : roundProjectPath);
|
|
84111
84892
|
// Note: Read before the first `[^]` rewrite of this round, which would overwrite the report recorded so far
|
|
84112
84893
|
const previousRunnerSignatures = resolvePreviousRunnerSignatures(nextPrompt);
|
|
84113
84894
|
setPromptRoundRunningState({ isRichUiEnabled, promptLabel, scriptPath, uiHandle });
|
|
@@ -84126,13 +84907,13 @@
|
|
|
84126
84907
|
for (let errorRetryAttempt = 0; errorRetryAttempt <= MAX_RETRY_ATTEMPTS_AFTER_ERROR; errorRetryAttempt++) {
|
|
84127
84908
|
try {
|
|
84128
84909
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
84129
|
-
const result = await
|
|
84910
|
+
const result = await runPromptWithCheckFeedback({
|
|
84130
84911
|
runner,
|
|
84131
84912
|
prompt: codexPrompt,
|
|
84132
84913
|
scriptPath,
|
|
84133
84914
|
projectPath: roundProjectPath,
|
|
84134
84915
|
promptLabel,
|
|
84135
|
-
|
|
84916
|
+
checkCommand: options.checkCommand,
|
|
84136
84917
|
preserveArtifactsOnSuccess: options.preserveLogs,
|
|
84137
84918
|
logPath,
|
|
84138
84919
|
onAttemptStarted: (nextAttemptCount) => {
|
|
@@ -84172,7 +84953,9 @@
|
|
|
84172
84953
|
lastError = error;
|
|
84173
84954
|
// Note: A harness which is not logged in answers every retry the same way, so the user gets
|
|
84174
84955
|
// the sign-in instructions right away instead of after every retry has waited its delay
|
|
84175
|
-
if (error instanceof AuthenticationError ||
|
|
84956
|
+
if (error instanceof AuthenticationError ||
|
|
84957
|
+
error instanceof CoderCheckSetupError ||
|
|
84958
|
+
errorRetryAttempt >= MAX_RETRY_ATTEMPTS_AFTER_ERROR) {
|
|
84176
84959
|
break;
|
|
84177
84960
|
}
|
|
84178
84961
|
await waitAfterErrorBeforeRetry({
|
|
@@ -84414,13 +85197,15 @@
|
|
|
84414
85197
|
* harness, model and thinking level did it and everything that harness has written while doing it.
|
|
84415
85198
|
*/
|
|
84416
85199
|
async function recordPromptRoundTrace(options) {
|
|
85200
|
+
var _a, _b;
|
|
84417
85201
|
const { options: runOptions, nextPrompt, runnerMetadata, promptExecutionStartedDate, attemptCount, logPath, outcome, } = options;
|
|
84418
85202
|
await writePromptRunTrace({
|
|
85203
|
+
projectPath: (_b = (_a = runOptions.workspace) === null || _a === void 0 ? void 0 : _a.projectPath) !== null && _b !== void 0 ? _b : runOptions.projectPath,
|
|
84419
85204
|
file: nextPrompt.file,
|
|
84420
85205
|
section: nextPrompt.section,
|
|
84421
85206
|
...runnerMetadata,
|
|
84422
85207
|
thinkingLevel: runOptions.thinkingLevel,
|
|
84423
|
-
|
|
85208
|
+
checkCommand: runOptions.checkCommand,
|
|
84424
85209
|
attemptCount,
|
|
84425
85210
|
startedDate: promptExecutionStartedDate,
|
|
84426
85211
|
finishedDate: moment__default["default"](),
|
|
@@ -85018,12 +85803,12 @@
|
|
|
85018
85803
|
* @private function of runCodexPrompts
|
|
85019
85804
|
*/
|
|
85020
85805
|
async function runIsolatedPromptRound(options) {
|
|
85021
|
-
var _a, _b, _c, _d, _e, _f;
|
|
85806
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
85022
85807
|
const { nextPrompt, promptLabel, isRichUiEnabled, uiHandle, waitForRequestedPause } = options;
|
|
85023
|
-
const projectPath = (_c = (_a = options.projectPath) !== null && _a !== void 0 ? _a : (_b = options.options.workspace) === null || _b === void 0 ? void 0 : _b.projectPath) !== null && _c !== void 0 ? _c : process.cwd();
|
|
85808
|
+
const projectPath = (_d = (_c = (_a = options.projectPath) !== null && _a !== void 0 ? _a : (_b = options.options.workspace) === null || _b === void 0 ? void 0 : _b.projectPath) !== null && _c !== void 0 ? _c : options.options.projectPath) !== null && _d !== void 0 ? _d : process.cwd();
|
|
85024
85809
|
// Note: The original project is left untouched by the isolated round itself, so its scope covers exactly
|
|
85025
85810
|
// the prompt status update and the changes the merge brings back from the worktree
|
|
85026
|
-
const originalProjectCommitScope = await captureCoderCommitScope((
|
|
85811
|
+
const originalProjectCommitScope = await captureCoderCommitScope((_e = options.options.workspace) !== null && _e !== void 0 ? _e : projectPath);
|
|
85027
85812
|
const worktree = await createCoderIsolationWorktree({
|
|
85028
85813
|
projectPath,
|
|
85029
85814
|
repositoryRoot: originalProjectCommitScope.repositoryRoot,
|
|
@@ -85031,16 +85816,44 @@
|
|
|
85031
85816
|
});
|
|
85032
85817
|
announceIsolatedRoundStart(worktree, promptLabel, isRichUiEnabled);
|
|
85033
85818
|
try {
|
|
85034
|
-
const isolatedProjectPath = path.join(worktree.worktreePath, path.relative((
|
|
85819
|
+
const isolatedProjectPath = path.join(worktree.worktreePath, path.relative((_f = originalProjectCommitScope.repositoryRoot) !== null && _f !== void 0 ? _f : projectPath, projectPath));
|
|
85035
85820
|
// This newly created working tree has its own metadata. Keep the project's repository-relative
|
|
85036
85821
|
// location so its harness and verification use the same project as the original invocation.
|
|
85037
85822
|
const isolatedWorkspace = await $resolveWorkspaceRepository(isolatedProjectPath);
|
|
85823
|
+
const isolatedOptions = {
|
|
85824
|
+
...options.options,
|
|
85825
|
+
workspace: isolatedWorkspace,
|
|
85826
|
+
projectPath: isolatedWorkspace.projectPath,
|
|
85827
|
+
agent: mapProjectReferenceToWorktree(options.options.agent, (_g = originalProjectCommitScope.repositoryRoot) !== null && _g !== void 0 ? _g : projectPath, worktree.worktreePath),
|
|
85828
|
+
context: mapProjectReferenceToWorktree(options.options.context, (_h = originalProjectCommitScope.repositoryRoot) !== null && _h !== void 0 ? _h : projectPath, worktree.worktreePath),
|
|
85829
|
+
autoPush: false,
|
|
85830
|
+
};
|
|
85831
|
+
const projectContext = await resolveCoderProjectContext(isolatedOptions);
|
|
85832
|
+
const agent = await resolveCoderAgent(isolatedOptions.agent, isolatedWorkspace.projectPath, {
|
|
85833
|
+
defaultRole: DEFAULT_CODER_AGENT_ROLE,
|
|
85834
|
+
isInitializationAllowed: false,
|
|
85835
|
+
});
|
|
85836
|
+
// Status updates, traces and commits belong to the same checkout as the harness and checks.
|
|
85837
|
+
// Copy the parsed data too, so a failed isolated round does not mutate the original queue in memory.
|
|
85838
|
+
const isolatedFile = {
|
|
85839
|
+
...nextPrompt.file,
|
|
85840
|
+
path: path.join(isolatedWorkspace.projectPath, path.relative(projectPath, nextPrompt.file.path)),
|
|
85841
|
+
lines: [...nextPrompt.file.lines],
|
|
85842
|
+
sections: nextPrompt.file.sections.map((section) => ({ ...section })),
|
|
85843
|
+
};
|
|
85038
85844
|
await runPromptRound({
|
|
85039
85845
|
...options,
|
|
85846
|
+
nextPrompt: { file: isolatedFile, section: isolatedFile.sections[nextPrompt.section.index] },
|
|
85040
85847
|
projectPath: isolatedWorkspace.projectPath,
|
|
85848
|
+
// Temporary scripts and raw logs deliberately outlive the worktree; PRDs and traces are merged.
|
|
85849
|
+
artifactsProjectPath: projectPath,
|
|
85850
|
+
resolvedCoderContext: projectContext.context,
|
|
85851
|
+
resolvedAgentSystemMessage: agent === null || agent === void 0 ? void 0 : agent.systemMessage,
|
|
85041
85852
|
// Note: The isolated commit must never reach the remote, the merged commit on the original branch is pushed instead
|
|
85042
|
-
options: { ...
|
|
85853
|
+
options: { ...isolatedOptions, projectContext },
|
|
85043
85854
|
});
|
|
85855
|
+
// Keep the display/commit identity in sync without writing to the original checkout before merging.
|
|
85856
|
+
Object.assign(nextPrompt.section, isolatedFile.sections[nextPrompt.section.index]);
|
|
85044
85857
|
}
|
|
85045
85858
|
catch (error) {
|
|
85046
85859
|
// Note: The worktree keeps whatever the failed round produced, which would be lost by deleting it here
|
|
@@ -85061,7 +85874,7 @@
|
|
|
85061
85874
|
await commitChanges(buildCommitMessage(nextPrompt.file, nextPrompt.section), {
|
|
85062
85875
|
autoPush: options.options.autoPush,
|
|
85063
85876
|
relevantPaths: await resolveCoderCommitScopePaths(originalProjectCommitScope),
|
|
85064
|
-
projectPath: (
|
|
85877
|
+
projectPath: (_j = originalProjectCommitScope.repositoryRoot) !== null && _j !== void 0 ? _j : projectPath,
|
|
85065
85878
|
});
|
|
85066
85879
|
await removeCoderIsolationWorktree(worktree);
|
|
85067
85880
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Merged \`${worktree.taskName}\` into \`${worktree.baseBranchName}\``);
|
|
@@ -85070,9 +85883,23 @@
|
|
|
85070
85883
|
* Records a failed isolation merge in the original project and keeps the worktree for a manual merge.
|
|
85071
85884
|
*/
|
|
85072
85885
|
async function recordIsolationMergeFailure(options, worktree, failureDetails) {
|
|
85073
|
-
var _a, _b;
|
|
85886
|
+
var _a, _b, _c, _d;
|
|
85074
85887
|
const { nextPrompt, runnerMetadata, isRichUiEnabled, uiHandle } = options;
|
|
85075
85888
|
const mergeFailureError = buildCoderIsolationMergeFailureError(worktree, failureDetails);
|
|
85889
|
+
const repositoryRoot = (_b = (_a = options.options.workspace) === null || _a === void 0 ? void 0 : _a.repositoryRoot) !== null && _b !== void 0 ? _b : worktree.projectPath;
|
|
85890
|
+
const tracePath = buildPromptRunTracePath(nextPrompt.file, nextPrompt.section);
|
|
85891
|
+
const isolatedTracePath = path.join(worktree.worktreePath, path.relative(repositoryRoot, tracePath));
|
|
85892
|
+
// The failed merge did not bring back the worktree's trace. Preserve it beside the failure report.
|
|
85893
|
+
await promises.mkdir(path.dirname(tracePath), { recursive: true });
|
|
85894
|
+
let isTraceCopied = false;
|
|
85895
|
+
try {
|
|
85896
|
+
await promises.copyFile(isolatedTracePath, tracePath);
|
|
85897
|
+
isTraceCopied = true;
|
|
85898
|
+
}
|
|
85899
|
+
catch (error) {
|
|
85900
|
+
if (error.code !== 'ENOENT')
|
|
85901
|
+
throw error;
|
|
85902
|
+
}
|
|
85076
85903
|
markPromptIsolationMergeFailed(nextPrompt.file, nextPrompt.section, worktree);
|
|
85077
85904
|
await writePromptFile(nextPrompt.file);
|
|
85078
85905
|
const errorLogPath = await writePromptErrorLog({
|
|
@@ -85084,13 +85911,11 @@
|
|
|
85084
85911
|
});
|
|
85085
85912
|
await commitChanges(buildCoderIsolationMergeFailureCommitMessage(worktree), {
|
|
85086
85913
|
autoPush: options.options.autoPush,
|
|
85087
|
-
projectPath: (
|
|
85088
|
-
// Note: The round itself has already succeeded, so it has left its run trace in the original project.
|
|
85089
|
-
// It belongs to this commit, which is the only one this task still gets.
|
|
85914
|
+
projectPath: (_d = (_c = options.options.workspace) === null || _c === void 0 ? void 0 : _c.repositoryRoot) !== null && _d !== void 0 ? _d : worktree.projectPath,
|
|
85090
85915
|
relevantPaths: [
|
|
85091
85916
|
nextPrompt.file.path,
|
|
85092
85917
|
errorLogPath,
|
|
85093
|
-
|
|
85918
|
+
...(isTraceCopied ? [tracePath] : []),
|
|
85094
85919
|
].map((path) => { var _a, _b; return toProjectRelativeGitPath((_b = (_a = options.options.workspace) === null || _a === void 0 ? void 0 : _a.repositoryRoot) !== null && _b !== void 0 ? _b : worktree.projectPath, path); }),
|
|
85095
85920
|
});
|
|
85096
85921
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(mergeFailureError.message);
|
|
@@ -85131,8 +85956,8 @@
|
|
|
85131
85956
|
/**
|
|
85132
85957
|
* Builds a label that identifies the prompt section by index.
|
|
85133
85958
|
*/
|
|
85134
|
-
function buildPromptLabel(file, section) {
|
|
85135
|
-
return `${path.relative(
|
|
85959
|
+
function buildPromptLabel(file, section, projectPath = process.cwd()) {
|
|
85960
|
+
return `${path.relative(projectPath, file.path).replace(/\\/g, '/')}#${section.index + 1}`;
|
|
85136
85961
|
}
|
|
85137
85962
|
|
|
85138
85963
|
/**
|
|
@@ -85360,18 +86185,20 @@
|
|
|
85360
86185
|
}
|
|
85361
86186
|
|
|
85362
86187
|
/**
|
|
85363
|
-
* Creates the one queue prompt used to repair a pre-existing
|
|
86188
|
+
* Creates the one queue prompt used to repair a pre-existing project check failure.
|
|
85364
86189
|
*/
|
|
85365
|
-
async function
|
|
86190
|
+
async function createCheckBeforeRepairPrompt(options) {
|
|
85366
86191
|
const description = spaceTrim((block) => `
|
|
85367
|
-
Fix the existing
|
|
86192
|
+
Fix the existing check failures before implementing any queued coding tasks.
|
|
86193
|
+
|
|
86194
|
+
The check command \`${options.checkCommand}\` failed before coding started. Leave the project ready for the remaining coding prompts.
|
|
85368
86195
|
|
|
85369
|
-
|
|
86196
|
+
${block(CHECK_REPAIR_INSTRUCTIONS)}
|
|
85370
86197
|
|
|
85371
|
-
##
|
|
86198
|
+
## Check output
|
|
85372
86199
|
|
|
85373
86200
|
\`\`\`
|
|
85374
|
-
${block(
|
|
86201
|
+
${block(limitCheckOutput(options.checkOutput))}
|
|
85375
86202
|
\`\`\`
|
|
85376
86203
|
`);
|
|
85377
86204
|
const createdPrompt = await addCoderPrompt({
|
|
@@ -85384,50 +86211,56 @@
|
|
|
85384
86211
|
const section = promptFile.sections[0];
|
|
85385
86212
|
if (!section) {
|
|
85386
86213
|
throw new UnexpectedError(spaceTrim(`
|
|
85387
|
-
The pre-coding
|
|
86214
|
+
The pre-coding check repair prompt was created at \`${createdPrompt.filePath}\` without a runnable section.
|
|
85388
86215
|
`));
|
|
85389
86216
|
}
|
|
85390
86217
|
return { file: promptFile, section };
|
|
85391
86218
|
}
|
|
85392
86219
|
|
|
85393
86220
|
/**
|
|
85394
|
-
* Runs the configured
|
|
86221
|
+
* Runs the configured check command before the first coding prompt.
|
|
85395
86222
|
*/
|
|
85396
|
-
async function
|
|
85397
|
-
var _a, _b;
|
|
85398
|
-
|
|
85399
|
-
const
|
|
85400
|
-
|
|
85401
|
-
|
|
86223
|
+
async function runCheckBefore(options) {
|
|
86224
|
+
var _a, _b, _c, _d, _e, _f;
|
|
86225
|
+
(_a = options.signal) === null || _a === void 0 ? void 0 : _a.throwIfAborted();
|
|
86226
|
+
const runPromptCheckCommandExecutor = (_b = options.runPromptCheckCommandExecutor) !== null && _b !== void 0 ? _b : runPromptCheckCommand;
|
|
86227
|
+
const initialCheckStatusMessage = `Running initial checks before the agent coding starts: ${options.checkCommand}`;
|
|
86228
|
+
await ((_c = options.waitForPauseCheckpoint) === null || _c === void 0 ? void 0 : _c.call(options, {
|
|
86229
|
+
checkpointLabel: 'running initial checks before the agent coding starts',
|
|
85402
86230
|
phase: 'verifying',
|
|
85403
|
-
statusMessage:
|
|
86231
|
+
statusMessage: initialCheckStatusMessage,
|
|
85404
86232
|
}));
|
|
85405
|
-
|
|
86233
|
+
(_d = options.signal) === null || _d === void 0 ? void 0 : _d.throwIfAborted();
|
|
86234
|
+
console.info(colors__default["default"].gray(initialCheckStatusMessage));
|
|
85406
86235
|
try {
|
|
85407
|
-
const
|
|
85408
|
-
command: options.
|
|
86236
|
+
const checkOutput = await runPromptCheckCommandExecutor({
|
|
86237
|
+
command: options.checkCommand,
|
|
85409
86238
|
projectPath: options.projectPath,
|
|
85410
86239
|
scriptPath: buildTemporaryPromptScriptPath({
|
|
85411
86240
|
projectPath: options.projectPath,
|
|
85412
86241
|
scriptDirectoryName: 'coder-prompts',
|
|
85413
|
-
sourceFileName: '
|
|
86242
|
+
sourceFileName: 'check-before',
|
|
85414
86243
|
}),
|
|
86244
|
+
...(options.signal ? { signal: options.signal } : {}),
|
|
85415
86245
|
});
|
|
85416
|
-
|
|
85417
|
-
|
|
86246
|
+
(_e = options.signal) === null || _e === void 0 ? void 0 : _e.throwIfAborted();
|
|
86247
|
+
console.info(colors__default["default"].green('Pre-coding checks passed.'));
|
|
86248
|
+
return { isPassed: true, checkOutput };
|
|
85418
86249
|
}
|
|
85419
86250
|
catch (error) {
|
|
85420
|
-
|
|
85421
|
-
|
|
85422
|
-
|
|
85423
|
-
|
|
86251
|
+
if (error instanceof CoderCheckSetupError || ((_f = options.signal) === null || _f === void 0 ? void 0 : _f.aborted))
|
|
86252
|
+
throw error;
|
|
86253
|
+
const checkOutput = formatUnknownErrorMessage(error);
|
|
86254
|
+
console.error(colors__default["default"].red('Pre-coding checks failed.'));
|
|
86255
|
+
console.error(checkOutput);
|
|
86256
|
+
return { isPassed: false, checkOutput };
|
|
85424
86257
|
}
|
|
85425
86258
|
}
|
|
85426
86259
|
|
|
85427
86260
|
/**
|
|
85428
|
-
* Commit message for files changed by a successful or failed pre-coding
|
|
86261
|
+
* Commit message for files changed by a successful or failed pre-coding check in repair mode.
|
|
85429
86262
|
*/
|
|
85430
|
-
const
|
|
86263
|
+
const PRE_CODING_CHECK_CHANGES_COMMIT_MESSAGE = 'chore: Apply changes made by pre-coding checks';
|
|
85431
86264
|
/**
|
|
85432
86265
|
* Main entry point for running prompts with the selected agent.
|
|
85433
86266
|
*
|
|
@@ -85436,10 +86269,15 @@
|
|
|
85436
86269
|
* @public exported from `@promptbook/cli`
|
|
85437
86270
|
*/
|
|
85438
86271
|
async function runCodexPrompts(providedOptions) {
|
|
85439
|
-
var _a, _b, _c, _d;
|
|
85440
|
-
const
|
|
85441
|
-
validateCoderRunOptions(
|
|
85442
|
-
|
|
86272
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
86273
|
+
const normalizedOptions = normalizeRunOptions(providedOptions !== null && providedOptions !== void 0 ? providedOptions : parseRunOptions(process.argv.slice(2)));
|
|
86274
|
+
validateCoderRunOptions(normalizedOptions);
|
|
86275
|
+
// CLI-preflighted workspaces are already canonical. For direct runs without an explicit project path, preserve
|
|
86276
|
+
// `process.cwd()` as written because macOS may expose the same temporary directory through `/var` and `/private/var`.
|
|
86277
|
+
const projectPath = (_b = (_a = normalizedOptions.workspace) === null || _a === void 0 ? void 0 : _a.projectPath) !== null && _b !== void 0 ? _b : ((providedOptions === null || providedOptions === void 0 ? void 0 : providedOptions.projectPath) === undefined
|
|
86278
|
+
? normalizedOptions.projectPath
|
|
86279
|
+
: await resolveProjectDirectory(normalizedOptions.projectPath));
|
|
86280
|
+
const options = { ...normalizedOptions, projectPath };
|
|
85443
86281
|
resetCoderRunControls();
|
|
85444
86282
|
const runStartDate = moment__default["default"]();
|
|
85445
86283
|
const { isRichUiEnabled, progressDisplay, uiHandle } = createRunDisplays(options, runStartDate);
|
|
@@ -85457,20 +86295,25 @@
|
|
|
85457
86295
|
startPauseListenerIfNeeded(isRichUiEnabled);
|
|
85458
86296
|
let subscriptionUsageRefresh;
|
|
85459
86297
|
try {
|
|
85460
|
-
const
|
|
86298
|
+
const projectContext = (_d = options.projectContext) !== null && _d !== void 0 ? _d : (await resolveCoderProjectContext({
|
|
86299
|
+
...options,
|
|
86300
|
+
projectPath,
|
|
86301
|
+
}));
|
|
86302
|
+
if (await runDryRunIfRequested(options, (_e = projectContext.agentBook) === null || _e === void 0 ? void 0 : _e.agentReferences)) {
|
|
86303
|
+
return;
|
|
86304
|
+
}
|
|
86305
|
+
await assertProjectCheckIsConfigured(options.checkCommand, projectPath);
|
|
86306
|
+
const resolvedCoderContext = projectContext.context;
|
|
85461
86307
|
const resolvedCoderAgent = await resolveCoderAgent(options.agent, projectPath, {
|
|
85462
|
-
defaultRole:
|
|
86308
|
+
defaultRole: DEFAULT_CODER_AGENT_ROLE,
|
|
85463
86309
|
isInitializationAllowed: !options.dryRun,
|
|
85464
86310
|
});
|
|
85465
86311
|
const resolvedAgentSystemMessage = resolvedCoderAgent === null || resolvedCoderAgent === void 0 ? void 0 : resolvedCoderAgent.systemMessage;
|
|
85466
|
-
if (await runDryRunIfRequested(options, resolvedCoderAgent === null || resolvedCoderAgent === void 0 ? void 0 : resolvedCoderAgent.agentReferences)) {
|
|
85467
|
-
return;
|
|
85468
|
-
}
|
|
85469
86312
|
if (!options.noCommit && resolvedCoderAgent) {
|
|
85470
86313
|
await commitInitializedAgentBooks(projectPath, resolvedCoderAgent.createdAgentBookPaths, options.workspace);
|
|
85471
86314
|
}
|
|
85472
86315
|
const { runner: harnessRunner, actualRunnerModel, runnerMetadata: harnessRunnerMetadata, } = resolvePromptRunner(options);
|
|
85473
|
-
const runner = createCoderTeamPromptRunner(harnessRunner, options.agent);
|
|
86316
|
+
const runner = createCoderTeamPromptRunner(harnessRunner, options.agent, projectPath, (_f = options.workspace) === null || _f === void 0 ? void 0 : _f.repositoryRoot);
|
|
85474
86317
|
// Note: The harness only knows itself, so the Book agent it runs as is joined here - this is the single
|
|
85475
86318
|
// place where the whole run report of prompt status lines and run traces is put together
|
|
85476
86319
|
const runnerMetadata = {
|
|
@@ -85501,7 +86344,7 @@
|
|
|
85501
86344
|
let previousRoundStartTime;
|
|
85502
86345
|
let previousRoundEndTime;
|
|
85503
86346
|
let completedRunCount = 0;
|
|
85504
|
-
let
|
|
86347
|
+
let hasRunCheckBefore = false;
|
|
85505
86348
|
// Note: Only the very first round resumes the interrupted prompt, every later round starts from a clean tree
|
|
85506
86349
|
let isContinuingInterruptedPrompt = options.gitChanges === 'continue';
|
|
85507
86350
|
while (just(true)) {
|
|
@@ -85516,11 +86359,11 @@
|
|
|
85516
86359
|
options,
|
|
85517
86360
|
isRichUiEnabled,
|
|
85518
86361
|
});
|
|
85519
|
-
if (!
|
|
86362
|
+
if (!hasRunCheckBefore && options.checkBefore !== 'no') {
|
|
85520
86363
|
await waitForRequestedPause({
|
|
85521
|
-
checkpointLabel: 'loading prompts before running initial
|
|
86364
|
+
checkpointLabel: 'loading prompts before running initial checks',
|
|
85522
86365
|
phase: 'loading',
|
|
85523
|
-
statusMessage: 'Loading prompts before running initial
|
|
86366
|
+
statusMessage: 'Loading prompts before running initial checks...',
|
|
85524
86367
|
});
|
|
85525
86368
|
await loadPromptQueueSnapshot({
|
|
85526
86369
|
options,
|
|
@@ -85531,8 +86374,8 @@
|
|
|
85531
86374
|
isContinuingInterruptedPrompt,
|
|
85532
86375
|
});
|
|
85533
86376
|
}
|
|
85534
|
-
if (!
|
|
85535
|
-
hasWaitedForStart = await
|
|
86377
|
+
if (!hasRunCheckBefore) {
|
|
86378
|
+
hasWaitedForStart = await runCheckBeforeIfNeeded({
|
|
85536
86379
|
options,
|
|
85537
86380
|
runner,
|
|
85538
86381
|
runnerMetadata,
|
|
@@ -85545,7 +86388,7 @@
|
|
|
85545
86388
|
hasWaitedForStart,
|
|
85546
86389
|
isContinuingInterruptedPrompt,
|
|
85547
86390
|
});
|
|
85548
|
-
|
|
86391
|
+
hasRunCheckBefore = true;
|
|
85549
86392
|
}
|
|
85550
86393
|
await waitForRequestedPause({
|
|
85551
86394
|
checkpointLabel: 'loading prompts',
|
|
@@ -85561,6 +86404,7 @@
|
|
|
85561
86404
|
isContinuingInterruptedPrompt,
|
|
85562
86405
|
});
|
|
85563
86406
|
hasShownUpcomingTasks || (hasShownUpcomingTasks = showUpcomingTasksOnce({
|
|
86407
|
+
projectPath,
|
|
85564
86408
|
hasShownUpcomingTasks,
|
|
85565
86409
|
promptFiles: promptQueueSnapshot.promptFiles,
|
|
85566
86410
|
stats: promptQueueSnapshot.stats,
|
|
@@ -85591,7 +86435,7 @@
|
|
|
85591
86435
|
return;
|
|
85592
86436
|
}
|
|
85593
86437
|
const nextPrompt = promptQueueSnapshot.nextPrompt;
|
|
85594
|
-
const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section);
|
|
86438
|
+
const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section, projectPath);
|
|
85595
86439
|
// Wait between prompt rounds (skipped for the first round)
|
|
85596
86440
|
if (previousRoundStartTime !== undefined && previousRoundEndTime !== undefined) {
|
|
85597
86441
|
await waitBetweenPromptRoundsIfNeeded({
|
|
@@ -85626,7 +86470,7 @@
|
|
|
85626
86470
|
phase: 'loading',
|
|
85627
86471
|
statusMessage: 'Checking the working tree...',
|
|
85628
86472
|
});
|
|
85629
|
-
await ensureWorkingTreeClean((
|
|
86473
|
+
await ensureWorkingTreeClean((_h = (_g = options.workspace) === null || _g === void 0 ? void 0 : _g.repositoryRoot) !== null && _h !== void 0 ? _h : projectPath);
|
|
85630
86474
|
}
|
|
85631
86475
|
const currentRoundStartTime = Date.now();
|
|
85632
86476
|
// Note: An isolated round implements the prompt in a temporary worktree and merges it back afterwards
|
|
@@ -85688,7 +86532,7 @@
|
|
|
85688
86532
|
* Pulls the latest repository state before loading prompts when the feature is enabled.
|
|
85689
86533
|
*/
|
|
85690
86534
|
async function pullLatestChangesIfEnabled(options) {
|
|
85691
|
-
var _a;
|
|
86535
|
+
var _a, _b;
|
|
85692
86536
|
const { options: runOptions, isRichUiEnabled } = options;
|
|
85693
86537
|
if (!runOptions.autoPull || runOptions.dryRun) {
|
|
85694
86538
|
return;
|
|
@@ -85696,7 +86540,7 @@
|
|
|
85696
86540
|
if (!isRichUiEnabled) {
|
|
85697
86541
|
console.info(colors__default["default"].gray('Pulling latest changes before the next prompt...'));
|
|
85698
86542
|
}
|
|
85699
|
-
await pullLatestChanges((_a = runOptions.workspace) === null || _a === void 0 ? void 0 : _a.repositoryRoot);
|
|
86543
|
+
await pullLatestChanges((_b = (_a = runOptions.workspace) === null || _a === void 0 ? void 0 : _a.repositoryRoot) !== null && _b !== void 0 ? _b : runOptions.projectPath);
|
|
85700
86544
|
}
|
|
85701
86545
|
/**
|
|
85702
86546
|
* Creates the progress display and rich UI handles used during the run.
|
|
@@ -85721,19 +86565,19 @@
|
|
|
85721
86565
|
* Normalizes legacy and current priority options into one validated run option shape.
|
|
85722
86566
|
*/
|
|
85723
86567
|
function normalizeRunOptions(options) {
|
|
85724
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
85725
|
-
const
|
|
85726
|
-
const normalizedTestCommand = (_b = options.testCommand) === null || _b === void 0 ? void 0 : _b.trim();
|
|
86568
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
86569
|
+
const checkBefore = (_a = options.checkBefore) !== null && _a !== void 0 ? _a : 'no';
|
|
85727
86570
|
const priorityFilter = normalizePriorityFilter({
|
|
85728
86571
|
priority: options.priority,
|
|
85729
|
-
minimumPriority: (
|
|
85730
|
-
maximumPriority: (
|
|
86572
|
+
minimumPriority: (_b = options.minimumPriority) !== null && _b !== void 0 ? _b : (_c = options.priorityFilter) === null || _c === void 0 ? void 0 : _c.minimumPriority,
|
|
86573
|
+
maximumPriority: (_d = options.maximumPriority) !== null && _d !== void 0 ? _d : (_e = options.priorityFilter) === null || _e === void 0 ? void 0 : _e.maximumPriority,
|
|
85731
86574
|
});
|
|
85732
86575
|
return {
|
|
85733
86576
|
...options,
|
|
85734
|
-
|
|
85735
|
-
|
|
85736
|
-
|
|
86577
|
+
projectPath: (_h = (_g = (_f = options.workspace) === null || _f === void 0 ? void 0 : _f.projectPath) !== null && _g !== void 0 ? _g : options.projectPath) !== null && _h !== void 0 ? _h : process.cwd(),
|
|
86578
|
+
checkBefore,
|
|
86579
|
+
checkCommand: resolveCoderCheckCommand((_j = options.checkCommand) === null || _j === void 0 ? void 0 : _j.trim(), checkBefore),
|
|
86580
|
+
priority: (_k = priorityFilter.minimumPriority) !== null && _k !== void 0 ? _k : 0,
|
|
85737
86581
|
minimumPriority: priorityFilter.minimumPriority,
|
|
85738
86582
|
maximumPriority: priorityFilter.maximumPriority,
|
|
85739
86583
|
priorityFilter,
|
|
@@ -85742,63 +86586,63 @@
|
|
|
85742
86586
|
/**
|
|
85743
86587
|
* Runs the optional pre-coding verification and, when requested, its one repair prompt.
|
|
85744
86588
|
*/
|
|
85745
|
-
async function
|
|
85746
|
-
var _a, _b
|
|
86589
|
+
async function runCheckBeforeIfNeeded(options) {
|
|
86590
|
+
var _a, _b;
|
|
85747
86591
|
const { options: runOptions, runner, runnerMetadata, resolvedCoderContext, resolvedAgentSystemMessage, isRichUiEnabled, progressDisplay, uiHandle, waitForRequestedPause, hasWaitedForStart, isContinuingInterruptedPrompt, } = options;
|
|
85748
|
-
if (runOptions.
|
|
86592
|
+
if (runOptions.checkBefore === 'no') {
|
|
85749
86593
|
return hasWaitedForStart;
|
|
85750
86594
|
}
|
|
85751
|
-
if (!runOptions.
|
|
86595
|
+
if (!runOptions.checkCommand) {
|
|
85752
86596
|
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
85753
|
-
${'`--
|
|
86597
|
+
${'`--check-before ' + runOptions.checkBefore + '`'} requires a verification command.
|
|
85754
86598
|
|
|
85755
|
-
Pass one with ${'`--
|
|
86599
|
+
Pass one with ${'`--check <check-command>`'} or use the default ${'`npm run check`'} command.
|
|
85756
86600
|
`));
|
|
85757
86601
|
}
|
|
85758
86602
|
if (isCleanWorkingTreeRequired(runOptions.gitChanges, isContinuingInterruptedPrompt)) {
|
|
85759
86603
|
await waitForRequestedPause({
|
|
85760
|
-
checkpointLabel: 'checking the git working tree before
|
|
86604
|
+
checkpointLabel: 'checking the git working tree before checking',
|
|
85761
86605
|
phase: 'loading',
|
|
85762
|
-
statusMessage: 'Checking the working tree before
|
|
86606
|
+
statusMessage: 'Checking the working tree before checking...',
|
|
85763
86607
|
});
|
|
85764
|
-
await ensureWorkingTreeClean((_a = runOptions.workspace) === null || _a === void 0 ? void 0 : _a.repositoryRoot);
|
|
86608
|
+
await ensureWorkingTreeClean((_b = (_a = runOptions.workspace) === null || _a === void 0 ? void 0 : _a.repositoryRoot) !== null && _b !== void 0 ? _b : runOptions.projectPath);
|
|
85765
86609
|
}
|
|
85766
|
-
const
|
|
86610
|
+
const checkBeforeCommitScope = await captureCheckBeforeCommitScopeIfNeeded(runOptions);
|
|
85767
86611
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
85768
|
-
const
|
|
85769
|
-
|
|
85770
|
-
projectPath:
|
|
86612
|
+
const checkBeforeResult = await runCheckBefore({
|
|
86613
|
+
checkCommand: runOptions.checkCommand,
|
|
86614
|
+
projectPath: runOptions.projectPath,
|
|
85771
86615
|
waitForPauseCheckpoint: waitForRequestedPause,
|
|
85772
86616
|
}).finally(() => {
|
|
85773
86617
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
85774
86618
|
});
|
|
85775
|
-
await
|
|
86619
|
+
await commitCheckBeforeChangesIfNeeded({
|
|
85776
86620
|
runOptions,
|
|
85777
|
-
|
|
86621
|
+
checkBeforeCommitScope,
|
|
85778
86622
|
waitForRequestedPause,
|
|
85779
86623
|
});
|
|
85780
|
-
if (
|
|
86624
|
+
if (checkBeforeResult.isPassed) {
|
|
85781
86625
|
return hasWaitedForStart;
|
|
85782
86626
|
}
|
|
85783
|
-
const
|
|
85784
|
-
if (runOptions.
|
|
86627
|
+
const checkOutput = limitCheckOutput(checkBeforeResult.checkOutput);
|
|
86628
|
+
if (runOptions.checkBefore === 'yes-and-fail') {
|
|
85785
86629
|
throw new NotAllowed(_spaceTrim.spaceTrim((block) => `
|
|
85786
|
-
Pre-coding
|
|
86630
|
+
Pre-coding check command \`${runOptions.checkCommand}\` failed.
|
|
85787
86631
|
|
|
85788
86632
|
The coding agent was not started because the project was already failing before the first queued prompt.
|
|
85789
86633
|
|
|
85790
|
-
###
|
|
86634
|
+
### Check results
|
|
85791
86635
|
${'```'}
|
|
85792
|
-
${block(
|
|
86636
|
+
${block(checkOutput)}
|
|
85793
86637
|
${'```'}
|
|
85794
86638
|
`));
|
|
85795
86639
|
}
|
|
85796
|
-
const repairPrompt = await
|
|
85797
|
-
projectPath:
|
|
85798
|
-
|
|
85799
|
-
|
|
86640
|
+
const repairPrompt = await createCheckBeforeRepairPrompt({
|
|
86641
|
+
projectPath: runOptions.projectPath,
|
|
86642
|
+
checkCommand: runOptions.checkCommand,
|
|
86643
|
+
checkOutput,
|
|
85800
86644
|
});
|
|
85801
|
-
const repairPromptLabel = buildPromptLabelForDisplay(repairPrompt.file, repairPrompt.section);
|
|
86645
|
+
const repairPromptLabel = buildPromptLabelForDisplay(repairPrompt.file, repairPrompt.section, runOptions.projectPath);
|
|
85802
86646
|
const updatedHasWaitedForStart = await waitForPromptConfirmationIfNeeded({
|
|
85803
86647
|
options: runOptions,
|
|
85804
86648
|
nextPrompt: repairPrompt,
|
|
@@ -85826,36 +86670,36 @@
|
|
|
85826
86670
|
return updatedHasWaitedForStart;
|
|
85827
86671
|
}
|
|
85828
86672
|
/**
|
|
85829
|
-
* Captures the files present before a `yes-and-fix` pre-coding
|
|
86673
|
+
* Captures the files present before a `yes-and-fix` pre-coding check, so only changes made by that check can be committed.
|
|
85830
86674
|
*/
|
|
85831
|
-
async function
|
|
86675
|
+
async function captureCheckBeforeCommitScopeIfNeeded(runOptions) {
|
|
85832
86676
|
var _a;
|
|
85833
|
-
if (runOptions.
|
|
86677
|
+
if (runOptions.checkBefore !== 'yes-and-fix' || runOptions.noCommit) {
|
|
85834
86678
|
return undefined;
|
|
85835
86679
|
}
|
|
85836
|
-
return captureCoderCommitScope((_a = runOptions.workspace) !== null && _a !== void 0 ? _a :
|
|
86680
|
+
return captureCoderCommitScope((_a = runOptions.workspace) !== null && _a !== void 0 ? _a : runOptions.projectPath);
|
|
85837
86681
|
}
|
|
85838
86682
|
/**
|
|
85839
|
-
* Commits files changed by a `yes-and-fix` pre-coding
|
|
86683
|
+
* Commits files changed by a `yes-and-fix` pre-coding check before the coder continues to a queued or repair prompt.
|
|
85840
86684
|
*/
|
|
85841
|
-
async function
|
|
86685
|
+
async function commitCheckBeforeChangesIfNeeded(options) {
|
|
85842
86686
|
var _a;
|
|
85843
|
-
const { runOptions,
|
|
85844
|
-
if (!
|
|
86687
|
+
const { runOptions, checkBeforeCommitScope, waitForRequestedPause } = options;
|
|
86688
|
+
if (!checkBeforeCommitScope) {
|
|
85845
86689
|
return;
|
|
85846
86690
|
}
|
|
85847
|
-
const relevantPaths = await resolveCoderCommitScopePaths(
|
|
86691
|
+
const relevantPaths = await resolveCoderCommitScopePaths(checkBeforeCommitScope);
|
|
85848
86692
|
if (relevantPaths.length === 0) {
|
|
85849
86693
|
return;
|
|
85850
86694
|
}
|
|
85851
86695
|
await waitForRequestedPause({
|
|
85852
|
-
checkpointLabel: 'committing changes made by pre-coding
|
|
86696
|
+
checkpointLabel: 'committing changes made by pre-coding checks',
|
|
85853
86697
|
phase: 'verifying',
|
|
85854
|
-
statusMessage: 'Committing changes made by pre-coding
|
|
86698
|
+
statusMessage: 'Committing changes made by pre-coding checks...',
|
|
85855
86699
|
});
|
|
85856
|
-
await commitChanges(
|
|
86700
|
+
await commitChanges(PRE_CODING_CHECK_CHANGES_COMMIT_MESSAGE, {
|
|
85857
86701
|
autoPush: runOptions.autoPush,
|
|
85858
|
-
projectPath: (_a =
|
|
86702
|
+
projectPath: (_a = checkBeforeCommitScope.repositoryRoot) !== null && _a !== void 0 ? _a : checkBeforeCommitScope.projectPath,
|
|
85859
86703
|
relevantPaths,
|
|
85860
86704
|
});
|
|
85861
86705
|
}
|
|
@@ -85901,7 +86745,6 @@
|
|
|
85901
86745
|
* Runs the dry-run reporting mode and returns whether the main execution should stop.
|
|
85902
86746
|
*/
|
|
85903
86747
|
async function runDryRunIfRequested(options, agentReferences) {
|
|
85904
|
-
var _a, _b;
|
|
85905
86748
|
if (!options.dryRun) {
|
|
85906
86749
|
return false;
|
|
85907
86750
|
}
|
|
@@ -85910,7 +86753,7 @@
|
|
|
85910
86753
|
modelName: options.agentName ? resolveRunnerModel(options.agentName, options.model) : options.model,
|
|
85911
86754
|
agentReferences,
|
|
85912
86755
|
};
|
|
85913
|
-
const promptFiles = (await loadPromptFiles(path.join(
|
|
86756
|
+
const promptFiles = (await loadPromptFiles(path.join(options.projectPath, 'prompts'), {
|
|
85914
86757
|
isMissingDirectoryAllowed: true,
|
|
85915
86758
|
})).map((file) => ({
|
|
85916
86759
|
...file,
|
|
@@ -85919,7 +86762,7 @@
|
|
|
85919
86762
|
const stats = summarizePrompts(promptFiles, options.priorityFilter);
|
|
85920
86763
|
printStats(stats, options.priorityFilter);
|
|
85921
86764
|
console.info(colors__default["default"].yellow('Following prompts need to be written:'));
|
|
85922
|
-
printPromptsToBeWritten(promptFiles, options.priorityFilter);
|
|
86765
|
+
printPromptsToBeWritten(promptFiles, options.priorityFilter, options.projectPath);
|
|
85923
86766
|
return true;
|
|
85924
86767
|
}
|
|
85925
86768
|
/**
|
|
@@ -85934,7 +86777,7 @@
|
|
|
85934
86777
|
serverUrl: options.serverUrl,
|
|
85935
86778
|
priorityFilter: options.priorityFilter,
|
|
85936
86779
|
limit: options.limit,
|
|
85937
|
-
|
|
86780
|
+
checkCommand: options.checkCommand,
|
|
85938
86781
|
});
|
|
85939
86782
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('loading');
|
|
85940
86783
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Running prompts with ${runnerName}`);
|
|
@@ -85957,10 +86800,9 @@
|
|
|
85957
86800
|
* Loads prompt files, updates progress displays, and selects the next runnable prompt.
|
|
85958
86801
|
*/
|
|
85959
86802
|
async function loadPromptQueueSnapshot(options) {
|
|
85960
|
-
var _a, _b;
|
|
85961
86803
|
const { options: runOptions, isRichUiEnabled, progressDisplay, uiHandle, promptRunnerIdentity, isContinuingInterruptedPrompt, } = options;
|
|
85962
86804
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentScriptPath(undefined);
|
|
85963
|
-
const promptFiles = await loadPromptFiles(path.join(
|
|
86805
|
+
const promptFiles = await loadPromptFiles(path.join(runOptions.projectPath, 'prompts'));
|
|
85964
86806
|
const stats = summarizePrompts(promptFiles, runOptions.priorityFilter);
|
|
85965
86807
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.update(stats);
|
|
85966
86808
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.updateProgress(stats);
|
|
@@ -85987,10 +86829,10 @@
|
|
|
85987
86829
|
}
|
|
85988
86830
|
if (stats.toBeWritten > 0) {
|
|
85989
86831
|
console.info(colors__default["default"].yellow('Following prompts need to be written:'));
|
|
85990
|
-
printPromptsToBeWritten(promptFiles, priorityFilter);
|
|
86832
|
+
printPromptsToBeWritten(promptFiles, priorityFilter, options.projectPath);
|
|
85991
86833
|
console.info('');
|
|
85992
86834
|
}
|
|
85993
|
-
printUpcomingTasks(listUpcomingTasks(promptFiles, priorityFilter, promptRunnerIdentity));
|
|
86835
|
+
printUpcomingTasks(listUpcomingTasks(promptFiles, priorityFilter, promptRunnerIdentity, options.projectPath));
|
|
85994
86836
|
return true;
|
|
85995
86837
|
}
|
|
85996
86838
|
/**
|
|
@@ -86187,12 +87029,14 @@
|
|
|
86187
87029
|
return [
|
|
86188
87030
|
...options.promptFiles.map((promptFile) => buildCoderServerPromptFileResponse({
|
|
86189
87031
|
promptFile,
|
|
87032
|
+
projectPath: options.projectPath,
|
|
86190
87033
|
isFinished: false,
|
|
86191
87034
|
priorityFilter: options.priorityFilter,
|
|
86192
87035
|
activePrompt,
|
|
86193
87036
|
})),
|
|
86194
87037
|
...options.finishedPromptFiles.map((promptFile) => buildCoderServerPromptFileResponse({
|
|
86195
87038
|
promptFile,
|
|
87039
|
+
projectPath: options.projectPath,
|
|
86196
87040
|
isFinished: true,
|
|
86197
87041
|
priorityFilter: options.priorityFilter,
|
|
86198
87042
|
activePrompt,
|
|
@@ -86203,13 +87047,15 @@
|
|
|
86203
87047
|
* Builds one prompt-file response.
|
|
86204
87048
|
*/
|
|
86205
87049
|
function buildCoderServerPromptFileResponse(options) {
|
|
87050
|
+
var _a;
|
|
86206
87051
|
const { promptFile, isFinished, priorityFilter, activePrompt } = options;
|
|
86207
87052
|
return {
|
|
86208
87053
|
filePath: promptFile.path,
|
|
86209
87054
|
fileName: promptFile.name,
|
|
86210
|
-
relativeFilePath: path.relative(process.cwd(), promptFile.path).replace(/\\/gu, '/'),
|
|
87055
|
+
relativeFilePath: path.relative((_a = options.projectPath) !== null && _a !== void 0 ? _a : process.cwd(), promptFile.path).replace(/\\/gu, '/'),
|
|
86211
87056
|
isFinished,
|
|
86212
87057
|
sections: promptFile.sections.map((section) => buildCoderServerPromptSectionResponse({
|
|
87058
|
+
projectPath: options.projectPath,
|
|
86213
87059
|
promptFile,
|
|
86214
87060
|
section,
|
|
86215
87061
|
isFinished,
|
|
@@ -86224,7 +87070,7 @@
|
|
|
86224
87070
|
function buildCoderServerPromptSectionResponse(options) {
|
|
86225
87071
|
const { promptFile, section, isFinished, priorityFilter, activePrompt } = options;
|
|
86226
87072
|
const isUnwritten = isPromptToBeWritten(promptFile, section);
|
|
86227
|
-
const isActive = isPromptActive(promptFile, section, activePrompt);
|
|
87073
|
+
const isActive = isPromptActive(promptFile, section, activePrompt, options.projectPath);
|
|
86228
87074
|
const column = getPromptColumn({
|
|
86229
87075
|
section,
|
|
86230
87076
|
isFinished,
|
|
@@ -86239,7 +87085,7 @@
|
|
|
86239
87085
|
priority: section.priority,
|
|
86240
87086
|
summary: buildPromptSummary(promptFile, section),
|
|
86241
87087
|
content: buildCodexPrompt(promptFile, section),
|
|
86242
|
-
label: buildPromptLabelForDisplay(promptFile, section),
|
|
87088
|
+
label: buildPromptLabelForDisplay(promptFile, section, options.projectPath),
|
|
86243
87089
|
tags: buildPromptTags({
|
|
86244
87090
|
section,
|
|
86245
87091
|
isUnwritten,
|
|
@@ -86316,11 +87162,11 @@
|
|
|
86316
87162
|
/**
|
|
86317
87163
|
* Checks whether a parsed section is the prompt currently handled by the active agent.
|
|
86318
87164
|
*/
|
|
86319
|
-
function isPromptActive(promptFile, section, activePrompt) {
|
|
87165
|
+
function isPromptActive(promptFile, section, activePrompt, projectPath) {
|
|
86320
87166
|
if (!activePrompt || (section.status !== 'todo' && section.status !== 'in-progress')) {
|
|
86321
87167
|
return false;
|
|
86322
87168
|
}
|
|
86323
|
-
return buildPromptLabelForDisplay(promptFile, section) === activePrompt.label;
|
|
87169
|
+
return buildPromptLabelForDisplay(promptFile, section, projectPath) === activePrompt.label;
|
|
86324
87170
|
}
|
|
86325
87171
|
// Note: [🟡] Code for CLI command [coder server](scripts/run-codex-prompts/server/buildCoderServerPromptResponse.ts) should never be published outside of `@promptbook/cli`
|
|
86326
87172
|
|
|
@@ -87241,6 +88087,7 @@
|
|
|
87241
88087
|
const promptFiles = await loadPromptFilesSafely(promptsDir);
|
|
87242
88088
|
const finishedPromptFiles = await loadPromptFilesSafely(path.join(promptsDir, FINISHED_PROMPTS_DIRECTORY_NAME));
|
|
87243
88089
|
return buildCoderServerPromptFileResponses({
|
|
88090
|
+
projectPath: path.dirname(promptsDir),
|
|
87244
88091
|
promptFiles,
|
|
87245
88092
|
finishedPromptFiles,
|
|
87246
88093
|
priorityFilter,
|
|
@@ -87327,18 +88174,20 @@
|
|
|
87327
88174
|
* @private internal function of `ptbk coder server`
|
|
87328
88175
|
*/
|
|
87329
88176
|
async function runCodexPromptsServer(options) {
|
|
87330
|
-
var _a, _b, _c, _d;
|
|
87331
|
-
const { port, ...
|
|
87332
|
-
if (
|
|
87333
|
-
await runCodexPrompts(
|
|
88177
|
+
var _a, _b, _c, _d, _e;
|
|
88178
|
+
const { port, ...providedOptions } = options;
|
|
88179
|
+
if (providedOptions.dryRun) {
|
|
88180
|
+
await runCodexPrompts(providedOptions);
|
|
87334
88181
|
return;
|
|
87335
88182
|
}
|
|
88183
|
+
const workspace = (_a = providedOptions.workspace) !== null && _a !== void 0 ? _a : await $resolveWorkspaceRepository(providedOptions.projectPath);
|
|
88184
|
+
const runOptions = { ...providedOptions, workspace, projectPath: workspace.projectPath };
|
|
87336
88185
|
const serverUrl = `http://localhost:${port}`;
|
|
87337
88186
|
const uiState = new CoderRunUiState(moment__default["default"]());
|
|
87338
88187
|
const priorityFilter = normalizePriorityFilter({
|
|
87339
88188
|
priority: runOptions.priority,
|
|
87340
|
-
minimumPriority: (
|
|
87341
|
-
maximumPriority: (
|
|
88189
|
+
minimumPriority: (_b = runOptions.minimumPriority) !== null && _b !== void 0 ? _b : (_c = runOptions.priorityFilter) === null || _c === void 0 ? void 0 : _c.minimumPriority,
|
|
88190
|
+
maximumPriority: (_d = runOptions.maximumPriority) !== null && _d !== void 0 ? _d : (_e = runOptions.priorityFilter) === null || _e === void 0 ? void 0 : _e.maximumPriority,
|
|
87342
88191
|
});
|
|
87343
88192
|
const serverHandle = startCoderHttpServer({
|
|
87344
88193
|
port,
|