@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
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addProjectPathOption,
|
|
3
|
+
addProjectContextOption,
|
|
4
|
+
normalizeProjectCliOptions,
|
|
5
|
+
resolveProjectDirectory,
|
|
6
|
+
} from '../common/projectCliOptions';
|
|
1
7
|
import type {
|
|
2
8
|
Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
|
|
3
9
|
} from 'commander';
|
|
@@ -32,10 +38,13 @@ export function $initializeAgentChatCommand(program: Program): $side_effect {
|
|
|
32
38
|
command.requiredOption('--agent <agent-book-path>', 'Path to the agent .book file');
|
|
33
39
|
addPromptRunnerSelectionOptions(command);
|
|
34
40
|
addPromptRunnerRuntimeOptions(command);
|
|
35
|
-
command
|
|
41
|
+
addProjectPathOption(command);
|
|
42
|
+
addProjectContextOption(command);
|
|
36
43
|
|
|
37
44
|
command.action(
|
|
38
45
|
handleActionErrors(async (cliOptions, commandProgram) => {
|
|
46
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
47
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
39
48
|
const options = cliOptions as AgentCommandCliOptions;
|
|
40
49
|
const runnerOptions = normalizeAgentCommandRunnerOptions(options, commandProgram as Program);
|
|
41
50
|
const { runAgentChat } = await import('../../../../scripts/run-agent-chat/runAgentChat');
|
|
@@ -43,7 +52,7 @@ export function $initializeAgentChatCommand(program: Program): $side_effect {
|
|
|
43
52
|
await runAgentChat({
|
|
44
53
|
agentPath: resolveRequiredAgentPath(options),
|
|
45
54
|
context: options.context,
|
|
46
|
-
currentWorkingDirectory:
|
|
55
|
+
currentWorkingDirectory: projectPath,
|
|
47
56
|
...runnerOptions,
|
|
48
57
|
});
|
|
49
58
|
}),
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addProjectPathOption,
|
|
3
|
+
addProjectContextOption,
|
|
4
|
+
normalizeProjectCliOptions,
|
|
5
|
+
resolveProjectDirectory,
|
|
6
|
+
} from '../common/projectCliOptions';
|
|
1
7
|
import type {
|
|
2
8
|
Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
|
|
3
9
|
} from 'commander';
|
|
@@ -37,10 +43,13 @@ export function $initializeAgentExecCommand(program: Program): $side_effect {
|
|
|
37
43
|
command.requiredOption('--message <message>', 'User message to send to the agent');
|
|
38
44
|
addPromptRunnerSelectionOptions(command);
|
|
39
45
|
addPromptRunnerRuntimeOptions(command);
|
|
40
|
-
command
|
|
46
|
+
addProjectPathOption(command);
|
|
47
|
+
addProjectContextOption(command);
|
|
41
48
|
|
|
42
49
|
command.action(
|
|
43
50
|
handleActionErrors(async (cliOptions, commandProgram) => {
|
|
51
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
52
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
44
53
|
const options = cliOptions as AgentCommandCliOptions;
|
|
45
54
|
const runnerOptions = normalizeAgentCommandRunnerOptions(options, commandProgram as Program);
|
|
46
55
|
const { runAgentExec } = await import('../../../../scripts/run-agent-chat/runAgentExec');
|
|
@@ -49,7 +58,7 @@ export function $initializeAgentExecCommand(program: Program): $side_effect {
|
|
|
49
58
|
agentPath: resolveRequiredAgentPath(options),
|
|
50
59
|
context: options.context,
|
|
51
60
|
message: resolveRequiredAgentMessage(options),
|
|
52
|
-
currentWorkingDirectory:
|
|
61
|
+
currentWorkingDirectory: projectPath,
|
|
53
62
|
...runnerOptions,
|
|
54
63
|
});
|
|
55
64
|
}),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addProjectPathOption, normalizeProjectCliOptions, resolveProjectDirectory } from '../common/projectCliOptions';
|
|
1
2
|
import type {
|
|
2
3
|
Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
|
|
3
4
|
} from 'commander';
|
|
@@ -36,9 +37,12 @@ export function $initializeAgentInitCommand(program: Program): $side_effect {
|
|
|
36
37
|
`),
|
|
37
38
|
);
|
|
38
39
|
|
|
40
|
+
addProjectPathOption(command);
|
|
39
41
|
command.action(
|
|
40
|
-
handleActionErrors(async () => {
|
|
41
|
-
const
|
|
42
|
+
handleActionErrors(async (cliOptions) => {
|
|
43
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
44
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
45
|
+
const summary = await initializeAgentProjectConfiguration(projectPath);
|
|
42
46
|
printAgentInitializationSummary(summary);
|
|
43
47
|
}),
|
|
44
48
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { addProjectPathOption, normalizeProjectCliOptions, resolveProjectDirectory } from '../common/projectCliOptions';
|
|
1
2
|
import colors from 'colors';
|
|
2
3
|
import type {
|
|
3
4
|
Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
|
|
@@ -61,12 +62,18 @@ export function $initializeAgentRunnerCommand(
|
|
|
61
62
|
|
|
62
63
|
addPromptRunnerSelectionOptions(command);
|
|
63
64
|
addPromptRunnerExecutionOptions(command);
|
|
65
|
+
addProjectPathOption(command);
|
|
64
66
|
options.configureCommand?.(command);
|
|
65
67
|
|
|
66
68
|
command.action(
|
|
67
69
|
handleActionErrors(
|
|
68
70
|
async (cliOptions) => {
|
|
69
|
-
const
|
|
71
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
72
|
+
const projectPath = await resolveProjectDirectory(projectOptions.projectDirectory);
|
|
73
|
+
const runOptions = {
|
|
74
|
+
...createAgentRunOptionsFromCliOptions(cliOptions as AgentRunCliOptions),
|
|
75
|
+
projectPath,
|
|
76
|
+
};
|
|
70
77
|
const execute = await options.loadExecutor();
|
|
71
78
|
|
|
72
79
|
if (options.executionMode === 'watch') {
|
|
@@ -76,7 +83,7 @@ export function $initializeAgentRunnerCommand(
|
|
|
76
83
|
|
|
77
84
|
await runPersistentAgentWatch({
|
|
78
85
|
commandDisplayName: `ptbk agent-folder ${options.commandName}`,
|
|
79
|
-
logDirectoryPath:
|
|
86
|
+
logDirectoryPath: projectPath,
|
|
80
87
|
runWatch: async () => {
|
|
81
88
|
await execute(runOptions);
|
|
82
89
|
},
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from '../common/coderGitSyncCliOptions';
|
|
19
19
|
import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
|
|
20
20
|
import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
|
|
21
|
+
import { normalizeProjectCliOptions } from '../common/projectCliOptions';
|
|
21
22
|
import { handleActionErrors } from '../common/handleActionErrors';
|
|
22
23
|
import {
|
|
23
24
|
addQuestionsOption,
|
|
@@ -105,6 +106,7 @@ export function $initializeCoderAddCommand(program: Program): $side_effect {
|
|
|
105
106
|
|
|
106
107
|
command.action(
|
|
107
108
|
handleActionErrors(async (descriptionArgument: string | undefined, cliOptions) => {
|
|
109
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
108
110
|
const { priority, template: templateOption } = cliOptions as {
|
|
109
111
|
readonly priority: number;
|
|
110
112
|
readonly template?: string;
|
|
@@ -112,7 +114,11 @@ export function $initializeCoderAddCommand(program: Program): $side_effect {
|
|
|
112
114
|
|
|
113
115
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions as CoderGitSyncCliOptions);
|
|
114
116
|
const questionsOptions = normalizeQuestionsCliOptions(cliOptions as QuestionsCliOptions);
|
|
115
|
-
const workspace = await $preflightWorkspaceRepository({
|
|
117
|
+
const workspace = await $preflightWorkspaceRepository({
|
|
118
|
+
...projectOptions,
|
|
119
|
+
policy: 'mutate',
|
|
120
|
+
...questionsOptions,
|
|
121
|
+
});
|
|
116
122
|
const { projectPath } = workspace;
|
|
117
123
|
|
|
118
124
|
const description = await resolveCoderPromptDescription(descriptionArgument, questionsOptions);
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
|
|
3
3
|
} from 'commander';
|
|
4
|
-
import {
|
|
4
|
+
import { addProjectContextOption } from '../common/projectCliOptions';
|
|
5
|
+
import { CODER_DEFAULT_AGENT_BOOK_PATHS, DEFAULT_CODER_AGENT_ROLE, type CoderAgentRole } from './coderAgentRole';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Commander option bag for an optional Book agent used by coder commands.
|
|
@@ -34,5 +35,14 @@ export function addCoderAgentOption(command: Program, defaultRole?: CoderAgentRo
|
|
|
34
35
|
command.option('--agent <agent-book-path>', `${CODER_AGENT_OPTION_DESCRIPTION}. ${defaultDescription}`);
|
|
35
36
|
}
|
|
36
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Registers the shared optional persona and context for single-agent execution or authoring.
|
|
40
|
+
* @private internal CLI registration helper
|
|
41
|
+
*/
|
|
42
|
+
export function addCoderExecutionOptions(command: Program): void {
|
|
43
|
+
addCoderAgentOption(command, DEFAULT_CODER_AGENT_ROLE);
|
|
44
|
+
addProjectContextOption(command);
|
|
45
|
+
}
|
|
46
|
+
|
|
37
47
|
// Note: [🟡] Code for CLI coder agent options should never be published outside of `@promptbook/cli`
|
|
38
48
|
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
@@ -19,4 +19,10 @@ export const CODER_DEFAULT_AGENT_BOOK_PATHS = {
|
|
|
19
19
|
*/
|
|
20
20
|
export type CoderAgentRole = keyof typeof CODER_DEFAULT_AGENT_BOOK_PATHS;
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Shared persona for optional single-agent execution and authoring; capabilities belong to the command.
|
|
24
|
+
* @private internal constant of project CLI commands
|
|
25
|
+
*/
|
|
26
|
+
export const DEFAULT_CODER_AGENT_ROLE: CoderAgentRole = 'developer';
|
|
27
|
+
|
|
22
28
|
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
@@ -75,9 +75,9 @@ const CODER_REFERENCED_ARTIFACT_DEFINITIONS: ReadonlyArray<CoderReferencedArtifa
|
|
|
75
75
|
];
|
|
76
76
|
|
|
77
77
|
/**
|
|
78
|
-
* Initializes artifacts referenced by freshly added scripts.
|
|
78
|
+
* Initializes essential context and artifacts referenced by freshly added scripts. Books are ensured separately.
|
|
79
79
|
*
|
|
80
|
-
*
|
|
80
|
+
* AGENTS.md is essential even when every script already exists or uses implicit defaults.
|
|
81
81
|
*
|
|
82
82
|
* @private function of `initializeCoderProjectConfiguration`
|
|
83
83
|
*/
|
|
@@ -88,7 +88,7 @@ export async function ensureCoderReferencedArtifacts(
|
|
|
88
88
|
const ensuredArtifacts: Array<EnsuredCoderReferencedArtifact> = [];
|
|
89
89
|
|
|
90
90
|
for (const { relativeFilePath, ensureArtifactFile } of CODER_REFERENCED_ARTIFACT_DEFINITIONS) {
|
|
91
|
-
if (!referencedArtifactPaths.has(relativeFilePath)) {
|
|
91
|
+
if (relativeFilePath !== AGENTS_FILE_PATH && !referencedArtifactPaths.has(relativeFilePath)) {
|
|
92
92
|
ensuredArtifacts.push({ relativeFilePath, status: 'not-referenced' });
|
|
93
93
|
continue;
|
|
94
94
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { getDefaultCoderPackageJsonScripts } from './getDefaultCoderPackageJsonScripts';
|
|
2
2
|
import type { MergedStringRecordJsonFile } from './mergeStringRecordJsonFile';
|
|
3
3
|
import { mergeStringRecordJsonFile } from './mergeStringRecordJsonFile';
|
|
4
|
+
import { prepareCoderPackageJsonScripts, type PreparedCoderPackageJsonScripts } from './prepareCoderPackageJsonScripts';
|
|
5
|
+
import { findLegacyCoderCheckCallers } from './findLegacyCoderCheckCallers';
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
8
|
* Relative path to `package.json` in the initialized project.
|
|
@@ -10,17 +12,34 @@ const PACKAGE_JSON_FILE_PATH = 'package.json';
|
|
|
10
12
|
/**
|
|
11
13
|
* Ensures `package.json` contains the standalone Promptbook coder helper scripts.
|
|
12
14
|
*
|
|
13
|
-
*
|
|
15
|
+
* Project definitions are preserved; missing scripts and narrowly recognized generated migrations are applied.
|
|
14
16
|
*
|
|
15
17
|
* @private function of `initializeCoderProjectConfiguration`
|
|
16
18
|
*/
|
|
17
|
-
export async function ensureCoderPackageJsonFile(
|
|
18
|
-
|
|
19
|
+
export async function ensureCoderPackageJsonFile(
|
|
20
|
+
projectPath: string,
|
|
21
|
+
): Promise<MergedStringRecordJsonFile & Omit<PreparedCoderPackageJsonScripts, 'scripts'>> {
|
|
22
|
+
let preparation: PreparedCoderPackageJsonScripts;
|
|
23
|
+
const mergedFile = await mergeStringRecordJsonFile({
|
|
19
24
|
projectPath,
|
|
20
25
|
relativeFilePath: PACKAGE_JSON_FILE_PATH,
|
|
21
26
|
fieldPath: 'scripts',
|
|
22
27
|
nextEntries: getDefaultCoderPackageJsonScripts(),
|
|
28
|
+
transformExistingEntries: async (entries) => {
|
|
29
|
+
const legacyNames = Object.keys(entries).filter(
|
|
30
|
+
(name) => name === 'test-for-ptbk-coder' || name === 'check-for-ptbk-coder',
|
|
31
|
+
);
|
|
32
|
+
const externalCallers = await findLegacyCoderCheckCallers(projectPath, legacyNames);
|
|
33
|
+
preparation = prepareCoderPackageJsonScripts(entries, externalCallers);
|
|
34
|
+
return preparation.scripts;
|
|
35
|
+
},
|
|
23
36
|
});
|
|
37
|
+
return {
|
|
38
|
+
...mergedFile,
|
|
39
|
+
checkScriptSummary: preparation!.checkScriptSummary,
|
|
40
|
+
migrationInstructions: preparation!.migrationInstructions,
|
|
41
|
+
isCheckConfigured: preparation!.isCheckConfigured,
|
|
42
|
+
};
|
|
24
43
|
}
|
|
25
44
|
|
|
26
45
|
// Note: [🟡] Code for coder init package.json bootstrapping [ensureCoderPackageJsonFile](src/cli/cli-commands/coder/ensureCoderPackageJsonFile.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -6,6 +6,7 @@ import spaceTrim from 'spacetrim';
|
|
|
6
6
|
import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
7
7
|
import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
|
|
8
8
|
import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
|
|
9
|
+
import { normalizeProjectCliOptions } from '../common/projectCliOptions';
|
|
9
10
|
import { handleActionErrors } from '../common/handleActionErrors';
|
|
10
11
|
|
|
11
12
|
/**
|
|
@@ -31,7 +32,9 @@ export function $initializeCoderFindFreshEmojiTagCommand(program: Program): $sid
|
|
|
31
32
|
|
|
32
33
|
command.action(
|
|
33
34
|
handleActionErrors(async (cliOptions) => {
|
|
35
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
34
36
|
const workspace = await $preflightWorkspaceRepository({
|
|
37
|
+
...projectOptions,
|
|
35
38
|
policy: 'read-only',
|
|
36
39
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
37
40
|
});
|
|
@@ -15,6 +15,7 @@ import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
|
15
15
|
import { createPositiveIntegerOptionParser } from '../common/createPositiveIntegerOptionParser';
|
|
16
16
|
import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
|
|
17
17
|
import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
|
|
18
|
+
import { normalizeProjectCliOptions } from '../common/projectCliOptions';
|
|
18
19
|
import { handleActionErrors } from '../common/handleActionErrors';
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -57,12 +58,14 @@ export function $initializeCoderFindRefactorCandidatesCommand(program: Program):
|
|
|
57
58
|
|
|
58
59
|
command.action(
|
|
59
60
|
handleActionErrors(async (cliOptions) => {
|
|
61
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
60
62
|
const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL, limit } = cliOptions as {
|
|
61
63
|
readonly level?: RefactorCandidateLevel;
|
|
62
64
|
readonly limit?: number;
|
|
63
65
|
};
|
|
64
66
|
|
|
65
67
|
const workspace = await $preflightWorkspaceRepository({
|
|
68
|
+
...projectOptions,
|
|
66
69
|
policy: 'mutate',
|
|
67
70
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
68
71
|
});
|
|
@@ -4,6 +4,7 @@ import { assertsError } from '../../../errors/assertsError';
|
|
|
4
4
|
import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
5
5
|
import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
|
|
6
6
|
import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
|
|
7
|
+
import { normalizeProjectCliOptions } from '../common/projectCliOptions';
|
|
7
8
|
import { handleActionErrors } from '../common/handleActionErrors';
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -22,11 +23,13 @@ export function $initializeCoderFindUnwrittenCommand(program: Program): $side_ef
|
|
|
22
23
|
|
|
23
24
|
command.action(
|
|
24
25
|
handleActionErrors(async (cliOptions) => {
|
|
26
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
25
27
|
const { priority = 0 } = cliOptions as {
|
|
26
28
|
readonly priority?: number;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
const workspace = await $preflightWorkspaceRepository({
|
|
32
|
+
...projectOptions,
|
|
30
33
|
policy: 'read-only',
|
|
31
34
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
32
35
|
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { readFile, readdir } from 'fs/promises';
|
|
2
|
+
import type { Dirent } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
|
|
5
|
+
// cspell:ignore Procfile
|
|
6
|
+
|
|
7
|
+
/** Runtime/dependency/history directories do not contain maintained project callers. */
|
|
8
|
+
const IGNORED_CALLER_DIRECTORIES = new Set([
|
|
9
|
+
'node_modules',
|
|
10
|
+
'.git',
|
|
11
|
+
'.promptbook',
|
|
12
|
+
'.next',
|
|
13
|
+
'.tmp',
|
|
14
|
+
'dist',
|
|
15
|
+
'build',
|
|
16
|
+
'coverage',
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
/** Only Coder's known task-history paths are excluded; the same names elsewhere can hold active callers. */
|
|
20
|
+
const IGNORED_CALLER_HISTORY_PATHS = new Set(['prompts/done', 'prompts/traces']);
|
|
21
|
+
|
|
22
|
+
/** Source and workflow files whose references must be preserved during npm script migration. */
|
|
23
|
+
const CALLER_FILE_PATTERN = /\.(?:[cm]?jsx?|tsx?|json|ya?ml|md|sh|bash|ps1|cmd|bat|py|toml|xml|groovy)$/iu;
|
|
24
|
+
|
|
25
|
+
/** Conventional workflow files which have no filename extension. */
|
|
26
|
+
const CALLER_FILE_NAMES = new Set(['Makefile', 'Dockerfile', 'Jenkinsfile', 'Procfile']);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Finds external project callers conservatively; it never rewrites their shell expressions.
|
|
30
|
+
* @private migration safety check for the Coder initializer
|
|
31
|
+
*/
|
|
32
|
+
export async function findLegacyCoderCheckCallers(
|
|
33
|
+
projectPath: string,
|
|
34
|
+
legacyNames: ReadonlyArray<string>,
|
|
35
|
+
): Promise<Readonly<Record<string, ReadonlyArray<string>>>> {
|
|
36
|
+
const callers: Record<string, string[]> = Object.fromEntries(legacyNames.map((name) => [name, []]));
|
|
37
|
+
if (legacyNames.length === 0) return callers;
|
|
38
|
+
|
|
39
|
+
/** Scans maintained text files without following symlinks or inspecting runtime state. */
|
|
40
|
+
async function visit(relativeDirectory: string): Promise<void> {
|
|
41
|
+
let entries: Dirent[];
|
|
42
|
+
try {
|
|
43
|
+
entries = await readdir(join(projectPath, relativeDirectory), { withFileTypes: true });
|
|
44
|
+
} catch {
|
|
45
|
+
for (const legacyName of legacyNames)
|
|
46
|
+
callers[legacyName]!.push(`${relativeDirectory} (unreadable directory; review manually)`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
for (const entry of entries) {
|
|
50
|
+
const relativePath = relativeDirectory ? `${relativeDirectory}/${entry.name}` : entry.name;
|
|
51
|
+
if (entry.isSymbolicLink()) {
|
|
52
|
+
if (!IGNORED_CALLER_DIRECTORIES.has(entry.name)) {
|
|
53
|
+
for (const legacyName of legacyNames)
|
|
54
|
+
callers[legacyName]!.push(`${relativePath} (symbolic link; review manually)`);
|
|
55
|
+
}
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
if (entry.isDirectory()) {
|
|
59
|
+
if (!IGNORED_CALLER_DIRECTORIES.has(entry.name) && !IGNORED_CALLER_HISTORY_PATHS.has(relativePath))
|
|
60
|
+
await visit(relativePath);
|
|
61
|
+
} else if (entry.isFile() && (CALLER_FILE_PATTERN.test(entry.name) || CALLER_FILE_NAMES.has(entry.name))) {
|
|
62
|
+
try {
|
|
63
|
+
let content = await readFile(join(projectPath, relativePath), 'utf-8');
|
|
64
|
+
if (relativePath === 'package.json') {
|
|
65
|
+
// Script callers are already handled by the merge. Other project-owned metadata may also
|
|
66
|
+
// reference a script, so it must be included when deciding whether removal is safe.
|
|
67
|
+
const packageMetadata = JSON.parse(content);
|
|
68
|
+
delete packageMetadata.scripts;
|
|
69
|
+
content = JSON.stringify(packageMetadata);
|
|
70
|
+
}
|
|
71
|
+
for (const legacyName of legacyNames) {
|
|
72
|
+
if (content.includes(legacyName))
|
|
73
|
+
callers[legacyName]!.push(
|
|
74
|
+
relativePath === 'package.json' ? 'package.json (outside scripts)' : relativePath,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
} catch {
|
|
78
|
+
// An unreadable file cannot prove that deletion is safe. Keep the entry and explain why.
|
|
79
|
+
for (const legacyName of legacyNames)
|
|
80
|
+
callers[legacyName]!.push(`${relativePath} (unreadable; review manually)`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
await visit('');
|
|
86
|
+
return callers;
|
|
87
|
+
}
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from '../common/coderGitSyncCliOptions';
|
|
15
15
|
import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
|
|
16
16
|
import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
|
|
17
|
+
import { normalizeProjectCliOptions } from '../common/projectCliOptions';
|
|
17
18
|
import { handleActionErrors } from '../common/handleActionErrors';
|
|
18
19
|
import type { BoilerplateCount } from './boilerplateCount';
|
|
19
20
|
import {
|
|
@@ -65,6 +66,7 @@ export function $initializeCoderGenerateBoilerplatesCommand(program: Program): $
|
|
|
65
66
|
|
|
66
67
|
command.action(
|
|
67
68
|
handleActionErrors(async (cliOptions) => {
|
|
69
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
68
70
|
const { count: countOption, template: templateOption } = cliOptions as {
|
|
69
71
|
readonly count: string;
|
|
70
72
|
readonly template?: string;
|
|
@@ -73,6 +75,7 @@ export function $initializeCoderGenerateBoilerplatesCommand(program: Program): $
|
|
|
73
75
|
const boilerplateCount = parseBoilerplateCount(countOption);
|
|
74
76
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions as CoderGitSyncCliOptions);
|
|
75
77
|
const workspace = await $preflightWorkspaceRepository({
|
|
78
|
+
...projectOptions,
|
|
76
79
|
policy: 'mutate',
|
|
77
80
|
isAskingQuestionsEnabled: cliOptions.questions,
|
|
78
81
|
});
|
|
@@ -2,13 +2,13 @@ import { AGENTS_FILE_PATH } from './agentsFile';
|
|
|
2
2
|
import { DEFAULT_BOILERPLATE_COUNT_OPTION_VALUE } from './boilerplateCount';
|
|
3
3
|
import { COMMON_PROMPT_TEMPLATE_FILE_PATH } from './boilerplateTemplates';
|
|
4
4
|
import { CODER_DEVELOPER_AGENT_FILE_PATH } from './ensureCoderDeveloperAgentFile';
|
|
5
|
-
import { CODER_PLANNER_AGENT_FILE_PATH } from './ensureCoderRoleAgentFile';
|
|
6
5
|
import { formatDisplayPath } from './formatDisplayPath';
|
|
6
|
+
import { CHECK_SETUP_PLACEHOLDER_COMMAND } from '../../../../scripts/run-codex-prompts/checks/projectCheck';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Name of the npm script which `ptbk coder run` uses to verify the project.
|
|
10
10
|
*/
|
|
11
|
-
const
|
|
11
|
+
const CHECK_SCRIPT_NAME = 'check';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* One npm script initialized by `ptbk coder init`.
|
|
@@ -53,14 +53,13 @@ const DEFAULT_CODER_PACKAGE_JSON_SCRIPT_DEFINITIONS: ReadonlyArray<CoderPackageJ
|
|
|
53
53
|
{
|
|
54
54
|
scriptName: 'coder:plan',
|
|
55
55
|
scriptCommand: 'npx ptbk coder plan --harness openai-codex',
|
|
56
|
-
referencedArtifactPaths: [
|
|
56
|
+
referencedArtifactPaths: [CODER_DEVELOPER_AGENT_FILE_PATH, AGENTS_FILE_PATH, COMMON_PROMPT_TEMPLATE_FILE_PATH],
|
|
57
57
|
},
|
|
58
58
|
{
|
|
59
59
|
scriptName: 'coder:run',
|
|
60
60
|
scriptCommand: [
|
|
61
61
|
'npx ptbk coder run --harness openai-codex --thinking-level max',
|
|
62
|
-
`--
|
|
63
|
-
`--test "npm run ${CODER_TEST_SCRIPT_NAME}" --test-before yes-and-fix`,
|
|
62
|
+
`--check "npm run ${CHECK_SCRIPT_NAME}" --check-before yes-and-fix`,
|
|
64
63
|
].join(' '),
|
|
65
64
|
referencedArtifactPaths: [CODER_DEVELOPER_AGENT_FILE_PATH, AGENTS_FILE_PATH],
|
|
66
65
|
},
|
|
@@ -73,8 +72,8 @@ const DEFAULT_CODER_PACKAGE_JSON_SCRIPT_DEFINITIONS: ReadonlyArray<CoderPackageJ
|
|
|
73
72
|
{
|
|
74
73
|
// Note: The verification command of `coder:run` is a project-owned script, so every project can decide
|
|
75
74
|
// what "verified" means without touching the `coder:run` script itself
|
|
76
|
-
scriptName:
|
|
77
|
-
scriptCommand:
|
|
75
|
+
scriptName: CHECK_SCRIPT_NAME,
|
|
76
|
+
scriptCommand: CHECK_SETUP_PLACEHOLDER_COMMAND,
|
|
78
77
|
referencedArtifactPaths: [],
|
|
79
78
|
},
|
|
80
79
|
];
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from '../common/coderGitSyncCliOptions';
|
|
15
15
|
import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
|
|
16
16
|
import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
|
|
17
|
+
import { normalizeProjectCliOptions } from '../common/projectCliOptions';
|
|
17
18
|
import { handleActionErrors } from '../common/handleActionErrors';
|
|
18
19
|
import { $ensureHarnessInstallations } from '../common/harness/$ensureHarnessInstallations';
|
|
19
20
|
import { getHarnessDefinition } from '../common/harness/HarnessDefinition';
|
|
@@ -88,7 +89,7 @@ export function $initializeCoderInitCommand(program: Program): $side_effect {
|
|
|
88
89
|
- Adds missing local Lawyer and Copywriter TEAM references to Developer and Planner, preserving existing content
|
|
89
90
|
- Helpers advise on relevant tasks; declaring TEAM does not run them for every task
|
|
90
91
|
- Reports created, augmented, unchanged and unresolved Books; invalid or conflicting files are left untouched
|
|
91
|
-
-
|
|
92
|
+
- Missing AGENTS.md is initialized independently of scripts; existing content is preserved
|
|
92
93
|
|
|
93
94
|
Ensures required coding-agent environment variables in .env:
|
|
94
95
|
- CODING_AGENT_GIT_NAME
|
|
@@ -112,9 +113,14 @@ export function $initializeCoderInitCommand(program: Program): $side_effect {
|
|
|
112
113
|
|
|
113
114
|
command.action(
|
|
114
115
|
handleActionErrors(async (cliOptions) => {
|
|
116
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
115
117
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions as CoderGitSyncCliOptions);
|
|
116
118
|
const questionsOptions = normalizeQuestionsCliOptions(cliOptions as QuestionsCliOptions);
|
|
117
|
-
const workspace = await $preflightWorkspaceRepository({
|
|
119
|
+
const workspace = await $preflightWorkspaceRepository({
|
|
120
|
+
...projectOptions,
|
|
121
|
+
policy: 'initialize',
|
|
122
|
+
...questionsOptions,
|
|
123
|
+
});
|
|
118
124
|
const { projectPath } = workspace;
|
|
119
125
|
|
|
120
126
|
const completedSteps = [`Git repository ${workspace.repositoryStatus}: ${workspace.repositoryRoot}`];
|
|
@@ -38,6 +38,12 @@ export type CoderInitializationSummary = {
|
|
|
38
38
|
readonly addedPackageJsonScriptNames: ReadonlyArray<string>;
|
|
39
39
|
readonly referencedArtifactStatuses: ReadonlyArray<EnsuredCoderReferencedArtifact>;
|
|
40
40
|
readonly initializedEnvVariableNames: ReadonlyArray<string>;
|
|
41
|
+
/** Actual preserved or generated scope of the project check. */
|
|
42
|
+
readonly checkScriptSummary: string;
|
|
43
|
+
/** Manual steps needed for custom or conflicting legacy entries. */
|
|
44
|
+
readonly migrationInstructions: ReadonlyArray<string>;
|
|
45
|
+
/** Whether validation is configured rather than still requiring setup. */
|
|
46
|
+
readonly isCheckConfigured: boolean;
|
|
41
47
|
};
|
|
42
48
|
|
|
43
49
|
/**
|
|
@@ -85,10 +91,13 @@ export async function initializeCoderProjectConfiguration(
|
|
|
85
91
|
)!;
|
|
86
92
|
const { envFileStatus, initializedEnvVariableNames } = await completeStep('.env', ensureCoderEnvFile(projectPath));
|
|
87
93
|
const gitignoreFileStatus = await completeStep('.gitignore', ensureCoderGitignoreFile(projectPath));
|
|
88
|
-
const {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
94
|
+
const {
|
|
95
|
+
status: packageJsonFileStatus,
|
|
96
|
+
addedEntryKeys: addedPackageJsonScriptNames,
|
|
97
|
+
checkScriptSummary,
|
|
98
|
+
migrationInstructions,
|
|
99
|
+
isCheckConfigured,
|
|
100
|
+
} = await completeStep('package.json', ensureCoderPackageJsonFile(projectPath));
|
|
92
101
|
const vscodeSettingsFileStatus = await completeStep(
|
|
93
102
|
'.vscode/settings.json',
|
|
94
103
|
ensureCoderVscodeSettingsFile(projectPath),
|
|
@@ -119,6 +128,9 @@ export async function initializeCoderProjectConfiguration(
|
|
|
119
128
|
addedPackageJsonScriptNames,
|
|
120
129
|
referencedArtifactStatuses,
|
|
121
130
|
initializedEnvVariableNames,
|
|
131
|
+
checkScriptSummary,
|
|
132
|
+
migrationInstructions,
|
|
133
|
+
isCheckConfigured,
|
|
122
134
|
};
|
|
123
135
|
}
|
|
124
136
|
|
|
@@ -5,6 +5,7 @@ import { spaceTrim } from 'spacetrim';
|
|
|
5
5
|
import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
6
6
|
import { $preflightWorkspaceRepository } from '../common/workspaceRepository';
|
|
7
7
|
import { addWorkspaceRepositoryOptions } from '../common/workspaceRepositoryCliOptions';
|
|
8
|
+
import { normalizeProjectCliOptions } from '../common/projectCliOptions';
|
|
8
9
|
import { handleActionErrors } from '../common/handleActionErrors';
|
|
9
10
|
import { addPromptPriorityOptions } from '../common/promptPriorityCliOptions';
|
|
10
11
|
import type { PromptRunnerSelectionCliOptions } from '../common/promptRunnerCliOptions';
|
|
@@ -46,6 +47,7 @@ export function $initializeCoderListCommand(program: Program): $side_effect {
|
|
|
46
47
|
|
|
47
48
|
command.action(
|
|
48
49
|
handleActionErrors(async (cliOptions) => {
|
|
50
|
+
const projectOptions = normalizeProjectCliOptions(cliOptions);
|
|
49
51
|
const {
|
|
50
52
|
agent,
|
|
51
53
|
priority,
|
|
@@ -62,7 +64,10 @@ export function $initializeCoderListCommand(program: Program): $side_effect {
|
|
|
62
64
|
cliOptions as PromptRunnerSelectionCliOptions,
|
|
63
65
|
{ isAgentRequired: false },
|
|
64
66
|
);
|
|
65
|
-
const workspace = await $preflightWorkspaceRepository({
|
|
67
|
+
const workspace = await $preflightWorkspaceRepository({
|
|
68
|
+
...projectOptions,
|
|
69
|
+
policy: 'read-only',
|
|
70
|
+
});
|
|
66
71
|
const resolvedCoderAgentBook =
|
|
67
72
|
agent === undefined
|
|
68
73
|
? undefined
|
|
@@ -28,6 +28,10 @@ type MergeStringRecordJsonFileOptions = {
|
|
|
28
28
|
readonly fieldPath: string;
|
|
29
29
|
readonly nextEntries: Readonly<Record<string, string>>;
|
|
30
30
|
readonly ensureParentDirectoryPath?: string;
|
|
31
|
+
/** Optional narrowly scoped migration of existing entries before missing defaults are added. */
|
|
32
|
+
readonly transformExistingEntries?: (
|
|
33
|
+
entries: Readonly<Record<string, string>>,
|
|
34
|
+
) => Readonly<Record<string, string>> | Promise<Readonly<Record<string, string>>>;
|
|
31
35
|
};
|
|
32
36
|
|
|
33
37
|
/**
|
|
@@ -60,8 +64,8 @@ const DEFAULT_JSON_FILE_NEWLINE = '\n';
|
|
|
60
64
|
/**
|
|
61
65
|
* Ensures one JSON object field contains the provided string-record entries.
|
|
62
66
|
*
|
|
63
|
-
* Entries
|
|
64
|
-
*
|
|
67
|
+
* Entries are additive unless a caller explicitly supplies a scoped migration callback.
|
|
68
|
+
* Hand-tuned scripts and settings survive repeated `ptbk coder init`; migrations recognize generated entries only.
|
|
65
69
|
*
|
|
66
70
|
* @private function of `initializeCoderProjectConfiguration`
|
|
67
71
|
*/
|
|
@@ -71,6 +75,7 @@ export async function mergeStringRecordJsonFile({
|
|
|
71
75
|
fieldPath,
|
|
72
76
|
nextEntries,
|
|
73
77
|
ensureParentDirectoryPath,
|
|
78
|
+
transformExistingEntries,
|
|
74
79
|
}: MergeStringRecordJsonFileOptions): Promise<MergedStringRecordJsonFile> {
|
|
75
80
|
if (ensureParentDirectoryPath) {
|
|
76
81
|
await mkdir(join(projectPath, ensureParentDirectoryPath), { recursive: true });
|
|
@@ -83,7 +88,7 @@ export async function mergeStringRecordJsonFile({
|
|
|
83
88
|
const existingEntries = getStringRecordOrDefault(jsonObject[fieldPath], relativeFilePath, fieldPath);
|
|
84
89
|
|
|
85
90
|
const addedEntryKeys: Array<string> = [];
|
|
86
|
-
const mergedEntries = { ...existingEntries };
|
|
91
|
+
const mergedEntries = { ...((await transformExistingEntries?.(existingEntries)) ?? existingEntries) };
|
|
87
92
|
for (const [entryKey, entryValue] of Object.entries(nextEntries)) {
|
|
88
93
|
if (Object.prototype.hasOwnProperty.call(mergedEntries, entryKey)) {
|
|
89
94
|
// Note: The project already defines this entry, keep its own value untouched
|
|
@@ -93,8 +98,13 @@ export async function mergeStringRecordJsonFile({
|
|
|
93
98
|
mergedEntries[entryKey] = entryValue;
|
|
94
99
|
addedEntryKeys.push(entryKey);
|
|
95
100
|
}
|
|
101
|
+
for (const entryKey of Object.keys(mergedEntries)) {
|
|
102
|
+
if (!Object.prototype.hasOwnProperty.call(existingEntries, entryKey) && !addedEntryKeys.includes(entryKey)) {
|
|
103
|
+
addedEntryKeys.push(entryKey);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
96
106
|
|
|
97
|
-
const hasChanges = fileContent === undefined ||
|
|
107
|
+
const hasChanges = fileContent === undefined || JSON.stringify(mergedEntries) !== JSON.stringify(existingEntries);
|
|
98
108
|
if (!hasChanges) {
|
|
99
109
|
return { status: 'unchanged', addedEntryKeys };
|
|
100
110
|
}
|