@promptbook/cli 0.114.0-33 → 0.114.0-34

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.
Files changed (167) hide show
  1. package/esm/index.es.js +1254 -318
  2. package/esm/index.es.js.map +1 -1
  3. package/esm/scripts/run-codex-prompts/common/createFreeDiskSpaceGuard.d.ts +25 -0
  4. package/esm/scripts/run-codex-prompts/common/formatUnknownErrorDetails.d.ts +4 -0
  5. package/esm/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +21 -3
  6. package/esm/scripts/run-codex-prompts/main/listCoderPrompts.d.ts +1 -1
  7. package/esm/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +77 -0
  8. package/esm/scripts/run-codex-prompts/prompts/buildPromptRunTracePath.d.ts +10 -0
  9. package/esm/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +11 -6
  10. package/esm/scripts/run-codex-prompts/prompts/loadPromptFiles.d.ts +1 -1
  11. package/esm/scripts/run-codex-prompts/prompts/writePromptRunTrace.d.ts +19 -0
  12. package/esm/scripts/run-codex-prompts/runners/common/buildHarnessAuthenticationError.d.ts +20 -0
  13. package/esm/scripts/run-codex-prompts/runners/common/createAuthenticationAwarePromptRunner.d.ts +11 -0
  14. package/esm/scripts/run-codex-prompts/runners/common/extractHarnessAuthenticationFailureReason.d.ts +9 -0
  15. package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +3 -0
  16. package/esm/src/book-2.0/book-language-documentation/getSafeCodeBlock.d.ts +1 -1
  17. package/esm/src/book-components/Chat/MockedChat/MockedChat.test.d.ts +2 -0
  18. package/esm/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.d.ts +2 -1
  19. package/esm/src/cli/cli-commands/coder/agentCliOptions.d.ts +21 -0
  20. package/esm/src/cli/cli-commands/coder/boilerplateTemplates.d.ts +8 -21
  21. package/esm/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +33 -0
  22. package/esm/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +4 -2
  23. package/esm/src/cli/cli-commands/coder/ensureCoderVscodeSettingsFile.d.ts +2 -0
  24. package/esm/src/cli/cli-commands/coder/ensureDirectory.d.ts +6 -0
  25. package/esm/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.d.ts +6 -0
  26. package/esm/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +7 -5
  27. package/esm/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +19 -1
  28. package/esm/src/cli/cli-commands/coder/printCoderRunFailure.d.ts +6 -0
  29. package/esm/src/cli/cli-commands/common/$askForConfirmation.d.ts +4 -2
  30. package/esm/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.d.ts +12 -0
  31. package/esm/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.test.d.ts +1 -0
  32. package/esm/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.d.ts +11 -0
  33. package/esm/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.test.d.ts +1 -0
  34. package/esm/src/cli/cli-commands/common/disk-space/FreeDiskSpaceStatus.d.ts +33 -0
  35. package/esm/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.d.ts +6 -0
  36. package/esm/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.test.d.ts +1 -0
  37. package/esm/src/cli/cli-commands/common/disk-space/formatLowFreeDiskSpaceWarning.d.ts +10 -0
  38. package/esm/src/cli/cli-commands/common/disk-space/freeDiskSpaceConstants.d.ts +28 -0
  39. package/esm/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.d.ts +7 -0
  40. package/esm/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.test.d.ts +1 -0
  41. package/esm/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.d.ts +2 -1
  42. package/esm/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -2
  43. package/esm/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +26 -0
  44. package/esm/src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.d.ts +4 -2
  45. package/esm/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +2 -1
  46. package/esm/src/cli/cli-commands/common/questionsCliOptions.d.ts +45 -0
  47. package/esm/src/cli/cli-commands/common/questionsCliOptions.test.d.ts +1 -0
  48. package/esm/src/cli/common/$deprecateCliCommand.d.ts +3 -0
  49. package/esm/src/cli/common/$hideCliCommandFromHelp.d.ts +11 -0
  50. package/esm/src/cli/common/$hideCliCommandFromHelp.test.d.ts +1 -0
  51. package/esm/src/cli/common/$requireCliSubcommand.d.ts +18 -0
  52. package/esm/src/cli/common/$requireCliSubcommand.test.d.ts +1 -0
  53. package/esm/src/llm-providers/vercel/VercelExecutionToolsOptions.d.ts +5 -2
  54. package/esm/src/version.d.ts +1 -1
  55. package/package.json +8 -11
  56. package/src/book-2.0/book-language-documentation/getSafeCodeBlock.ts +1 -1
  57. package/src/book-components/Chat/MockedChat/MockedChat.tsx +25 -1
  58. package/src/cli/cli-commands/agent-folder.ts +2 -6
  59. package/src/cli/cli-commands/agent.ts +2 -6
  60. package/src/cli/cli-commands/agents-server.ts +2 -6
  61. package/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.ts +3 -0
  62. package/src/cli/cli-commands/coder/add.ts +27 -2
  63. package/src/cli/cli-commands/coder/agentCliOptions.ts +32 -0
  64. package/src/cli/cli-commands/coder/boilerplateTemplates.ts +17 -44
  65. package/src/cli/cli-commands/coder/coderReferencedArtifacts.ts +106 -0
  66. package/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.ts +4 -2
  67. package/src/cli/cli-commands/coder/ensureCoderVscodeSettingsFile.ts +5 -1
  68. package/src/cli/cli-commands/coder/ensureDirectory.ts +27 -1
  69. package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +99 -10
  70. package/src/cli/cli-commands/coder/init.ts +23 -14
  71. package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +18 -27
  72. package/src/cli/cli-commands/coder/list.ts +15 -3
  73. package/src/cli/cli-commands/coder/mergeStringRecordJsonFile.ts +31 -7
  74. package/src/cli/cli-commands/coder/ping.ts +25 -22
  75. package/src/cli/cli-commands/coder/printCoderRunFailure.ts +14 -0
  76. package/src/cli/cli-commands/coder/printInitializationSummary.ts +23 -16
  77. package/src/cli/cli-commands/coder/run.ts +34 -23
  78. package/src/cli/cli-commands/coder/server.ts +43 -32
  79. package/src/cli/cli-commands/coder.ts +2 -6
  80. package/src/cli/cli-commands/common/$askForConfirmation.ts +12 -2
  81. package/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.ts +35 -0
  82. package/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.ts +37 -0
  83. package/src/cli/cli-commands/common/disk-space/FreeDiskSpaceStatus.ts +39 -0
  84. package/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.ts +26 -0
  85. package/src/cli/cli-commands/common/disk-space/formatLowFreeDiskSpaceWarning.ts +33 -0
  86. package/src/cli/cli-commands/common/disk-space/freeDiskSpaceConstants.ts +33 -0
  87. package/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.ts +21 -0
  88. package/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.ts +17 -5
  89. package/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.ts +8 -3
  90. package/src/cli/cli-commands/common/harness/HarnessDefinition.ts +36 -0
  91. package/src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.ts +8 -3
  92. package/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.ts +13 -2
  93. package/src/cli/cli-commands/common/questionsCliOptions.ts +89 -0
  94. package/src/cli/cli-commands/run.ts +3 -1
  95. package/src/cli/common/$deprecateCliCommand.ts +5 -0
  96. package/src/cli/common/$hideCliCommandFromHelp.ts +27 -0
  97. package/src/cli/common/$requireCliSubcommand.ts +35 -0
  98. package/src/cli/promptbookCli.ts +13 -9
  99. package/src/llm-providers/vercel/VercelExecutionToolsOptions.ts +7 -2
  100. package/src/llm-providers/vercel/createExecutionToolsFromVercelProvider.ts +18 -17
  101. package/src/other/templates/getTemplatesPipelineCollection.ts +677 -881
  102. package/src/version.ts +2 -2
  103. package/src/versions.txt +1 -0
  104. package/umd/index.umd.js +1253 -317
  105. package/umd/index.umd.js.map +1 -1
  106. package/umd/scripts/run-codex-prompts/common/createFreeDiskSpaceGuard.d.ts +25 -0
  107. package/umd/scripts/run-codex-prompts/common/formatUnknownErrorDetails.d.ts +4 -0
  108. package/umd/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +21 -3
  109. package/umd/scripts/run-codex-prompts/main/listCoderPrompts.d.ts +1 -1
  110. package/umd/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +77 -0
  111. package/umd/scripts/run-codex-prompts/prompts/buildPromptRunTracePath.d.ts +10 -0
  112. package/umd/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +11 -6
  113. package/umd/scripts/run-codex-prompts/prompts/loadPromptFiles.d.ts +1 -1
  114. package/umd/scripts/run-codex-prompts/prompts/writePromptRunTrace.d.ts +19 -0
  115. package/umd/scripts/run-codex-prompts/runners/common/buildHarnessAuthenticationError.d.ts +20 -0
  116. package/umd/scripts/run-codex-prompts/runners/common/createAuthenticationAwarePromptRunner.d.ts +11 -0
  117. package/umd/scripts/run-codex-prompts/runners/common/extractHarnessAuthenticationFailureReason.d.ts +9 -0
  118. package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +3 -0
  119. package/umd/src/book-2.0/book-language-documentation/getSafeCodeBlock.d.ts +1 -1
  120. package/umd/src/book-components/Chat/MockedChat/MockedChat.test.d.ts +2 -0
  121. package/umd/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.d.ts +2 -1
  122. package/umd/src/cli/cli-commands/coder/agentCliOptions.d.ts +21 -0
  123. package/umd/src/cli/cli-commands/coder/boilerplateTemplates.d.ts +8 -21
  124. package/umd/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +33 -0
  125. package/umd/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +4 -2
  126. package/umd/src/cli/cli-commands/coder/ensureCoderVscodeSettingsFile.d.ts +2 -0
  127. package/umd/src/cli/cli-commands/coder/ensureDirectory.d.ts +6 -0
  128. package/umd/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.d.ts +6 -0
  129. package/umd/src/cli/cli-commands/coder/init.test.d.ts +1 -0
  130. package/umd/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +7 -5
  131. package/umd/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +19 -1
  132. package/umd/src/cli/cli-commands/coder/printCoderRunFailure.d.ts +6 -0
  133. package/umd/src/cli/cli-commands/common/$askForConfirmation.d.ts +4 -2
  134. package/umd/src/cli/cli-commands/common/$askForConfirmation.test.d.ts +1 -0
  135. package/umd/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.d.ts +12 -0
  136. package/umd/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.test.d.ts +1 -0
  137. package/umd/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.d.ts +11 -0
  138. package/umd/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.test.d.ts +1 -0
  139. package/umd/src/cli/cli-commands/common/disk-space/FreeDiskSpaceStatus.d.ts +33 -0
  140. package/umd/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.d.ts +6 -0
  141. package/umd/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.test.d.ts +1 -0
  142. package/umd/src/cli/cli-commands/common/disk-space/formatLowFreeDiskSpaceWarning.d.ts +10 -0
  143. package/umd/src/cli/cli-commands/common/disk-space/freeDiskSpaceConstants.d.ts +28 -0
  144. package/umd/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.d.ts +7 -0
  145. package/umd/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.test.d.ts +1 -0
  146. package/umd/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.d.ts +2 -1
  147. package/umd/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -2
  148. package/umd/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +26 -0
  149. package/umd/src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.d.ts +4 -2
  150. package/umd/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +2 -1
  151. package/umd/src/cli/cli-commands/common/questionsCliOptions.d.ts +45 -0
  152. package/umd/src/cli/cli-commands/common/questionsCliOptions.test.d.ts +1 -0
  153. package/umd/src/cli/common/$deprecateCliCommand.d.ts +3 -0
  154. package/umd/src/cli/common/$hideCliCommandFromHelp.d.ts +11 -0
  155. package/umd/src/cli/common/$hideCliCommandFromHelp.test.d.ts +1 -0
  156. package/umd/src/cli/common/$requireCliSubcommand.d.ts +18 -0
  157. package/umd/src/cli/common/$requireCliSubcommand.test.d.ts +1 -0
  158. package/umd/src/llm-providers/vercel/VercelExecutionToolsOptions.d.ts +5 -2
  159. package/umd/src/version.d.ts +1 -1
  160. package/esm/src/cli/cli-commands/coder/agentCodingFile.d.ts +0 -13
  161. package/esm/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +0 -29
  162. package/src/cli/cli-commands/coder/agentCodingFile.ts +0 -25
  163. package/src/cli/cli-commands/common/harnessUpdateCliOptions.ts +0 -46
  164. package/umd/src/cli/cli-commands/coder/agentCodingFile.d.ts +0 -13
  165. package/umd/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +0 -29
  166. /package/esm/src/cli/cli-commands/{common/harnessUpdateCliOptions.test.d.ts → coder/init.test.d.ts} +0 -0
  167. /package/{umd/src/cli/cli-commands/common/harnessUpdateCliOptions.test.d.ts → esm/src/cli/cli-commands/common/$askForConfirmation.test.d.ts} +0 -0
@@ -30,6 +30,23 @@ type MergeStringRecordJsonFileOptions = {
30
30
  readonly ensureParentDirectoryPath?: string;
31
31
  };
32
32
 
33
+ /**
34
+ * Result of one additive string-record merge into a JSON file.
35
+ *
36
+ * @private internal utility of `coder init` command
37
+ */
38
+ export type MergedStringRecordJsonFile = {
39
+ /**
40
+ * Status describing whether the JSON file had to be created or updated.
41
+ */
42
+ readonly status: InitializationStatus;
43
+
44
+ /**
45
+ * Keys which were missing in the JSON file and therefore added by the merge.
46
+ */
47
+ readonly addedEntryKeys: ReadonlyArray<string>;
48
+ };
49
+
33
50
  /**
34
51
  * Default indentation used when creating new JSON configuration files.
35
52
  */
@@ -43,6 +60,9 @@ const DEFAULT_JSON_FILE_NEWLINE = '\n';
43
60
  /**
44
61
  * Ensures one JSON object field contains the provided string-record entries.
45
62
  *
63
+ * Entries which the project already defines are **never** overridden - only missing keys are added,
64
+ * so hand-tuned scripts and settings survive every repeated `ptbk coder init`.
65
+ *
46
66
  * @private function of `initializeCoderProjectConfiguration`
47
67
  */
48
68
  export async function mergeStringRecordJsonFile({
@@ -51,7 +71,7 @@ export async function mergeStringRecordJsonFile({
51
71
  fieldPath,
52
72
  nextEntries,
53
73
  ensureParentDirectoryPath,
54
- }: MergeStringRecordJsonFileOptions): Promise<InitializationStatus> {
74
+ }: MergeStringRecordJsonFileOptions): Promise<MergedStringRecordJsonFile> {
55
75
  if (ensureParentDirectoryPath) {
56
76
  await mkdir(join(projectPath, ensureParentDirectoryPath), { recursive: true });
57
77
  }
@@ -62,23 +82,27 @@ export async function mergeStringRecordJsonFile({
62
82
  const jsonObject = fileContent === undefined ? {} : await parseJsonObjectFile(relativeFilePath, fileContent);
63
83
  const existingEntries = getStringRecordOrDefault(jsonObject[fieldPath], relativeFilePath, fieldPath);
64
84
 
65
- let hasChanges = fileContent === undefined;
85
+ const addedEntryKeys: Array<string> = [];
66
86
  const mergedEntries = { ...existingEntries };
67
87
  for (const [entryKey, entryValue] of Object.entries(nextEntries)) {
68
- if (mergedEntries[entryKey] !== entryValue) {
69
- mergedEntries[entryKey] = entryValue;
70
- hasChanges = true;
88
+ if (Object.prototype.hasOwnProperty.call(mergedEntries, entryKey)) {
89
+ // Note: The project already defines this entry, keep its own value untouched
90
+ continue;
71
91
  }
92
+
93
+ mergedEntries[entryKey] = entryValue;
94
+ addedEntryKeys.push(entryKey);
72
95
  }
73
96
 
97
+ const hasChanges = fileContent === undefined || addedEntryKeys.length > 0;
74
98
  if (!hasChanges) {
75
- return 'unchanged';
99
+ return { status: 'unchanged', addedEntryKeys };
76
100
  }
77
101
 
78
102
  const nextJsonObject: JsonObject = { ...jsonObject };
79
103
  nextJsonObject[fieldPath] = mergedEntries;
80
104
  await writeFile(absoluteFilePath, serializeJsonObject(nextJsonObject, formatting), 'utf-8');
81
- return fileContent === undefined ? 'created' : 'updated';
105
+ return { status: fileContent === undefined ? 'created' : 'updated', addedEntryKeys };
82
106
  }
83
107
 
84
108
  /**
@@ -6,10 +6,11 @@ import type { $side_effect } from '../../../utils/organization/$side_effect';
6
6
  import { handleActionErrors } from '../common/handleActionErrors';
7
7
  import { $ensureHarnessInstallations } from '../common/harness/$ensureHarnessInstallations';
8
8
  import {
9
- addHarnessUpdateOption,
10
- normalizeHarnessUpdateCliOptions,
11
- type HarnessUpdateCliOptions,
12
- } from '../common/harnessUpdateCliOptions';
9
+ addQuestionsOption,
10
+ normalizeQuestionsCliOptions,
11
+ QUESTIONS_DESCRIPTION,
12
+ type QuestionsCliOptions,
13
+ } from '../common/questionsCliOptions';
13
14
  import type { PromptRunnerSelectionCliOptions } from '../common/promptRunnerCliOptions';
14
15
  import {
15
16
  addPromptRunnerRuntimeOptions,
@@ -30,24 +31,28 @@ import { $ensureCoderHarnessGitignoreRules } from './$ensureCoderHarnessGitignor
30
31
  export function $initializeCoderPingCommand(program: Program): $side_effect {
31
32
  const command = program.command('ping');
32
33
  command.description(
33
- spaceTrim(`
34
- Send one tiny dummy prompt to a harness and model to measure and warm them up
34
+ spaceTrim(
35
+ (block) => `
36
+ Send one tiny dummy prompt to a harness and model to measure and warm them up
35
37
 
36
- ${PROMPT_RUNNER_DESCRIPTION}
38
+ ${block(PROMPT_RUNNER_DESCRIPTION)}
37
39
 
38
- Features:
39
- - Verifies that the selected harness, model, thinking level and authentication really work
40
- - Reports the answer of the harness, the response time and the reported usage
41
- - Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
42
- - Optional --period keeps the quota window refreshing by pinging once per period until stopped
43
- - Makes no coding changes or commits; if the selected harness has missing local ignore rules, offers to add them to .gitignore
44
- - Checks that the selected harness is installed and up to date unless --no-harness-update is used
45
- - Use --no-ui to stream the raw harness output instead of only the compact result
46
- `),
40
+ ${block(QUESTIONS_DESCRIPTION)}
41
+
42
+ Features:
43
+ - Verifies that the selected harness, model, thinking level and authentication really work
44
+ - Reports the answer of the harness, the response time and the reported usage
45
+ - Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
46
+ - Optional --period keeps the quota window refreshing by pinging once per period until stopped
47
+ - Makes no coding changes or commits; if the selected harness has missing local ignore rules, offers to add them to .gitignore
48
+ - Checks that the selected harness is installed and up to date unless --no-questions is used
49
+ - Use --no-ui to stream the raw harness output instead of only the compact result
50
+ `,
51
+ ),
47
52
  );
48
53
 
49
54
  addPromptRunnerSelectionOptions(command);
50
- addHarnessUpdateOption(command);
55
+ addQuestionsOption(command);
51
56
  addPromptRunnerRuntimeOptions(command);
52
57
  command.option(
53
58
  '--period <duration>',
@@ -67,15 +72,13 @@ export function $initializeCoderPingCommand(program: Program): $side_effect {
67
72
  cliOptions as PromptRunnerSelectionCliOptions,
68
73
  { isAgentRequired: true },
69
74
  );
70
- const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(
71
- cliOptions as HarnessUpdateCliOptions,
72
- );
75
+ const questionsOptions = normalizeQuestionsCliOptions(cliOptions as QuestionsCliOptions);
73
76
 
74
77
  // Note: The period is validated before the harness installation check, so a mistyped duration fails fast
75
78
  const periodMs = parseOptionalPeriodDuration('--period', periodValue);
76
79
 
77
- await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
78
- await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
80
+ await $ensureHarnessInstallations([runnerOptions.agentName], questionsOptions);
81
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName, questionsOptions);
79
82
 
80
83
  const pingOptions = {
81
84
  agentName: runnerOptions.agentName,
@@ -0,0 +1,14 @@
1
+ import colors from 'colors';
2
+ import { formatUnknownErrorDetails } from '../../../../scripts/run-codex-prompts/common/formatUnknownErrorDetails';
3
+
4
+ /**
5
+ * Prints why a coder run has ended to the terminal.
6
+ *
7
+ * @private internal utility of `coder run` and `coder server` commands
8
+ */
9
+ export function printCoderRunFailure(error: Error): void {
10
+ console.error(colors.bgRed(`${error.name}`));
11
+ console.error(colors.red(formatUnknownErrorDetails(error)));
12
+ }
13
+
14
+ // Note: [🟡] Code for coder failure reporting [printCoderRunFailure](src/cli/cli-commands/coder/printCoderRunFailure.ts) should never be published outside of `@promptbook/cli`
@@ -1,8 +1,6 @@
1
1
  import colors from 'colors';
2
- import { AGENT_CODING_FILE_PATH } from './agentCodingFile';
3
- import { AGENTS_FILE_PATH } from './agentsFile';
4
2
  import type { InitializationStatus } from './boilerplateTemplates';
5
- import { CODER_DEVELOPER_AGENT_FILE_PATH } from './ensureCoderDeveloperAgentFile';
3
+ import type { CoderReferencedArtifactStatus } from './coderReferencedArtifacts';
6
4
  import { formatDisplayPath } from './formatDisplayPath';
7
5
  import type { CoderInitializationSummary } from './initializeCoderProjectConfiguration';
8
6
 
@@ -16,23 +14,25 @@ export function printInitializationSummary(summary: CoderInitializationSummary):
16
14
  printInitializationStatusLine('prompts/', summary.promptsDirectoryStatus);
17
15
  printInitializationStatusLine('prompts/done/', summary.promptsDoneDirectoryStatus);
18
16
  printInitializationStatusLine('prompts/templates/', summary.promptsTemplatesDirectoryStatus);
19
-
20
- for (const templateFileStatus of summary.promptTemplateFileStatuses) {
21
- printInitializationStatusLine(
22
- formatDisplayPath(templateFileStatus.relativeFilePath),
23
- templateFileStatus.status,
24
- );
25
- }
26
-
27
17
  printInitializationStatusLine('agents/', summary.agentsDirectoryStatus);
28
- printInitializationStatusLine(CODER_DEVELOPER_AGENT_FILE_PATH, summary.developerAgentFileStatus);
29
- printInitializationStatusLine(AGENTS_FILE_PATH, summary.agentsFileStatus);
30
- printInitializationStatusLine(AGENT_CODING_FILE_PATH, summary.agentCodingFileStatus);
31
18
  printInitializationStatusLine('.env', summary.envFileStatus);
32
19
  printInitializationStatusLine('.gitignore', summary.gitignoreFileStatus);
33
20
  printInitializationStatusLine('package.json', summary.packageJsonFileStatus);
34
21
  printInitializationStatusLine('.vscode/settings.json', summary.vscodeSettingsFileStatus);
35
22
 
23
+ for (const referencedArtifactStatus of summary.referencedArtifactStatuses) {
24
+ printInitializationStatusLine(
25
+ formatDisplayPath(referencedArtifactStatus.relativeFilePath),
26
+ referencedArtifactStatus.status,
27
+ );
28
+ }
29
+
30
+ if (summary.addedPackageJsonScriptNames.length > 0) {
31
+ printInitializationNote(`Added npm scripts: ${summary.addedPackageJsonScriptNames.join(', ')}`, colors.cyan);
32
+ } else {
33
+ printInitializationNote('All Promptbook coder npm scripts are already present.', colors.gray);
34
+ }
35
+
36
36
  if (summary.initializedEnvVariableNames.length > 0) {
37
37
  printInitializationNote(`Added env variables: ${summary.initializedEnvVariableNames.join(', ')}`, colors.cyan);
38
38
  } else {
@@ -43,7 +43,7 @@ export function printInitializationSummary(summary: CoderInitializationSummary):
43
43
  /**
44
44
  * Formats one initialization status into a human-readable label.
45
45
  */
46
- function formatInitializationStatus(status: InitializationStatus): string {
46
+ function formatInitializationStatus(status: InitializationStatus | CoderReferencedArtifactStatus): string {
47
47
  if (status === 'created') {
48
48
  return 'created';
49
49
  }
@@ -52,13 +52,20 @@ function formatInitializationStatus(status: InitializationStatus): string {
52
52
  return 'updated';
53
53
  }
54
54
 
55
+ if (status === 'not-referenced') {
56
+ return 'not referenced by the added scripts, kept as is';
57
+ }
58
+
55
59
  return 'unchanged';
56
60
  }
57
61
 
58
62
  /**
59
63
  * Prints one checked initialization-status line.
60
64
  */
61
- function printInitializationStatusLine(relativePath: string, status: InitializationStatus): void {
65
+ function printInitializationStatusLine(
66
+ relativePath: string,
67
+ status: InitializationStatus | CoderReferencedArtifactStatus,
68
+ ): void {
62
69
  console.info(colors.gray(`✔ ${relativePath}: ${formatInitializationStatus(status)}`));
63
70
  }
64
71
 
@@ -1,4 +1,3 @@
1
- import colors from 'colors';
2
1
  import {
3
2
  Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
4
3
  Option,
@@ -7,13 +6,16 @@ import { spaceTrim } from 'spacetrim';
7
6
  import { assertsError } from '../../../errors/assertsError';
8
7
  import type { $side_effect } from '../../../utils/organization/$side_effect';
9
8
  import { createPositiveIntegerOptionParser } from '../common/createPositiveIntegerOptionParser';
9
+ import { $assertSufficientFreeDiskSpace } from '../common/disk-space/$assertSufficientFreeDiskSpace';
10
10
  import { handleActionErrors } from '../common/handleActionErrors';
11
11
  import { $ensureHarnessInstallations } from '../common/harness/$ensureHarnessInstallations';
12
12
  import {
13
- addHarnessUpdateOption,
14
- normalizeHarnessUpdateCliOptions,
15
- type HarnessUpdateCliOptions,
16
- } from '../common/harnessUpdateCliOptions';
13
+ addQuestionsOption,
14
+ assertUserConfirmationIsAllowed,
15
+ normalizeQuestionsCliOptions,
16
+ QUESTIONS_DESCRIPTION,
17
+ type QuestionsCliOptions,
18
+ } from '../common/questionsCliOptions';
17
19
  import { $ensurePromptbookCliInstallations } from '../common/promptbook-cli/$ensurePromptbookCliInstallations';
18
20
  import type { PromptRunnerCliOptions } from '../common/promptRunnerCliOptions';
19
21
  import {
@@ -30,6 +32,8 @@ import {
30
32
  } from '../../../../scripts/run-codex-prompts/testing/TestBeforeMode';
31
33
  import { DEFAULT_WAIT_AFTER_ERROR_MS, parseOptionalWaitDuration } from './waitOptions';
32
34
  import { $ensureCoderHarnessGitignoreRules } from './$ensureCoderHarnessGitignoreRules';
35
+ import { addCoderAgentOption, type CoderAgentCliOptions } from './agentCliOptions';
36
+ import { printCoderRunFailure } from './printCoderRunFailure';
33
37
 
34
38
  /**
35
39
  * Initializes `coder run` command for Promptbook CLI utilities
@@ -41,10 +45,13 @@ import { $ensureCoderHarnessGitignoreRules } from './$ensureCoderHarnessGitignor
41
45
  export function $initializeCoderRunCommand(program: Program): $side_effect {
42
46
  const command = program.command('run');
43
47
  command.description(
44
- spaceTrim(`
48
+ spaceTrim(
49
+ (block) => `
45
50
  Execute coding prompts through selected AI agent
46
51
 
47
- ${PROMPT_RUNNER_DESCRIPTION}
52
+ ${block(PROMPT_RUNNER_DESCRIPTION)}
53
+
54
+ ${block(QUESTIONS_DESCRIPTION)}
48
55
 
49
56
  Features:
50
57
  - Automatically stages and commits changes with agent identity unless --no-commit is used
@@ -54,9 +61,11 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
54
61
  - Optional post-commit git push with explicit --auto-push opt-in
55
62
  - Optional pre-prompt git pull with explicit --auto-pull opt-in
56
63
  - Optional --isolate runs every prompt in its own temporary git worktree and merges it back when verified
64
+ - Saves the run trace of every round into prompts/traces/, named after its prompt file
57
65
  - Optional --preserve-logs keeps temp prompt/log artifacts after successful rounds
58
66
  - Optional --no-ui keeps plain streaming console output for logging and debugging
59
- - Checks that the selected harness is installed and up to date before the first prompt unless --no-harness-update is used
67
+ - Refuses to start on a nearly full disk and pauses the run when the free disk space becomes critical, unless --no-questions is used
68
+ - Checks that the selected harness is installed and up to date before the first prompt unless --no-questions is used
60
69
  - Offers to add missing project-local ignore rules for the selected harness
61
70
  - In interactive mode, checks local and global Promptbook CLI installations and offers to update them
62
71
  - Supports GPG signing of commits
@@ -64,16 +73,14 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
64
73
  - Optional post-prompt verification with test-feedback retries
65
74
  - Progress tracking and interactive P/S/X terminal controls
66
75
  - Dry-run mode to preview prompts
67
- `),
76
+ `,
77
+ ),
68
78
  );
69
79
 
70
80
  command.option('--dry-run', 'Print unwritten prompts without executing', false);
71
81
  addPromptRunnerSelectionOptions(command);
72
- addHarnessUpdateOption(command);
73
- command.option(
74
- '--agent <agent-book-path>',
75
- 'Path to a .book file whose compiled system message is prepended to each coding prompt',
76
- );
82
+ addQuestionsOption(command);
83
+ addCoderAgentOption(command);
77
84
  command.option(
78
85
  '--context <context-or-file>',
79
86
  'Append extra instructions either inline or from a file path relative to the current project',
@@ -187,16 +194,14 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
187
194
  readonly auto: boolean;
188
195
  readonly autoMigrate: boolean;
189
196
  readonly allowDestructiveAutoMigrate: boolean;
190
- } & PromptRunnerCliOptions;
197
+ } & PromptRunnerCliOptions & CoderAgentCliOptions;
191
198
 
192
199
  const configuredTestCommand = normalizeCommandOptionValue(test);
193
200
  const testCommand = configuredTestCommand ?? (testBefore === 'no' ? undefined : DEFAULT_CODER_TEST_COMMAND);
194
201
  const runnerOptions = normalizePromptRunnerCliOptions(cliOptions as PromptRunnerCliOptions, {
195
202
  isAgentRequired: !dryRun,
196
203
  });
197
- const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(
198
- cliOptions as HarnessUpdateCliOptions,
199
- );
204
+ const questionsOptions = normalizeQuestionsCliOptions(cliOptions as QuestionsCliOptions);
200
205
 
201
206
  // [1] Parse the wait options and --no-auto:
202
207
  // default: run automatically through the queue (no waiting between prompts)
@@ -206,12 +211,18 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
206
211
  // --wait-after-error: wait before retrying after an error (default 10m)
207
212
  const waitForUser = !auto;
208
213
 
209
- if (await $ensurePromptbookCliInstallations()) {
214
+ assertUserConfirmationIsAllowed({ ...questionsOptions, isWaitingForUser: waitForUser });
215
+
216
+ // Note: Checked before anything is installed or written, because installing a harness, updating the
217
+ // Promptbook CLI and coding itself all need the disk space which is missing
218
+ await $assertSufficientFreeDiskSpace(process.cwd());
219
+
220
+ if (await $ensurePromptbookCliInstallations(questionsOptions)) {
210
221
  return process.exit(0);
211
222
  }
212
223
 
213
- await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
214
- await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
224
+ await $ensureHarnessInstallations([runnerOptions.agentName], questionsOptions);
225
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName, questionsOptions);
215
226
 
216
227
  const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
217
228
  const waitBetweenPrompts = parseOptionalWaitDuration(waitBetweenPromptsValue, 0);
@@ -246,6 +257,7 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
246
257
  allowDestructiveAutoMigrate,
247
258
  autoPush: runnerOptions.autoPush,
248
259
  autoPull: runnerOptions.autoPull,
260
+ isAskingQuestionsEnabled: questionsOptions.isAskingQuestionsEnabled,
249
261
  };
250
262
 
251
263
  // Note: Import the function dynamically to avoid loading heavy dependencies until needed
@@ -256,8 +268,7 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
256
268
  await runCodexPrompts(runOptions);
257
269
  } catch (error) {
258
270
  assertsError(error);
259
- console.error(colors.bgRed(`${error.name}`));
260
- console.error(colors.red(error.stack || error.message));
271
+ printCoderRunFailure(error);
261
272
  return process.exit(1);
262
273
  }
263
274
 
@@ -1,4 +1,3 @@
1
- import colors from 'colors';
2
1
  import {
3
2
  Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
4
3
  Option,
@@ -9,13 +8,16 @@ import { assertsError } from '../../../errors/assertsError';
9
8
  import { NotAllowed } from '../../../errors/NotAllowed';
10
9
  import type { number_port } from '../../../types/number_positive';
11
10
  import type { $side_effect } from '../../../utils/organization/$side_effect';
11
+ import { $assertSufficientFreeDiskSpace } from '../common/disk-space/$assertSufficientFreeDiskSpace';
12
12
  import { handleActionErrors } from '../common/handleActionErrors';
13
13
  import { $ensureHarnessInstallations } from '../common/harness/$ensureHarnessInstallations';
14
14
  import {
15
- addHarnessUpdateOption,
16
- normalizeHarnessUpdateCliOptions,
17
- type HarnessUpdateCliOptions,
18
- } from '../common/harnessUpdateCliOptions';
15
+ addQuestionsOption,
16
+ assertUserConfirmationIsAllowed,
17
+ normalizeQuestionsCliOptions,
18
+ QUESTIONS_DESCRIPTION,
19
+ type QuestionsCliOptions,
20
+ } from '../common/questionsCliOptions';
19
21
  import type { PromptRunnerCliOptions } from '../common/promptRunnerCliOptions';
20
22
  import {
21
23
  addPromptRunnerExecutionOptions,
@@ -26,6 +28,8 @@ import {
26
28
  import { addPromptPriorityOptions } from '../common/promptPriorityCliOptions';
27
29
  import { DEFAULT_WAIT_AFTER_ERROR_MS, parseOptionalWaitDuration } from './waitOptions';
28
30
  import { $ensureCoderHarnessGitignoreRules } from './$ensureCoderHarnessGitignoreRules';
31
+ import { addCoderAgentOption, type CoderAgentCliOptions } from './agentCliOptions';
32
+ import { printCoderRunFailure } from './printCoderRunFailure';
29
33
 
30
34
  /**
31
35
  * Default port used by `ptbk coder server`.
@@ -47,21 +51,26 @@ const DEFAULT_CODER_SERVER_PORT = '4441';
47
51
  export function $initializeCoderServerCommand(program: Program): $side_effect {
48
52
  const command = program.command('server');
49
53
  command.description(
50
- spaceTrim(`
51
- Start a coder server that watches for prompts and serves a kanban web UI
54
+ spaceTrim(
55
+ (block) => `
56
+ Start a coder server that watches for prompts and serves a kanban web UI
52
57
 
53
- ${PROMPT_RUNNER_DESCRIPTION}
58
+ ${block(PROMPT_RUNNER_DESCRIPTION)}
54
59
 
55
- Features:
56
- - Runs the same prompt processing as \`ptbk coder run\`
57
- - Checks that the selected harness is installed and up to date on startup unless --no-harness-update is used
58
- - Offers to add missing project-local ignore rules for the selected harness
59
- - Does not exit when all prompts are done; polls for new prompt files instead
60
- - Serves a kanban board at http://localhost:<port> for visual progress tracking
61
- - Allows editing prompt files directly from the browser (Trello-style)
62
- - Play / pause button in the browser stays in sync with the CLI pause state
63
- - Terminal controls match \`ptbk coder run\`: P pause/resume, S skip waiting, X end after current prompt
64
- `),
60
+ ${block(QUESTIONS_DESCRIPTION)}
61
+
62
+ Features:
63
+ - Runs the same prompt processing as \`ptbk coder run\`
64
+ - Refuses to start on a nearly full disk and pauses the run when the free disk space becomes critical, unless --no-questions is used
65
+ - Checks that the selected harness is installed and up to date on startup unless --no-questions is used
66
+ - Offers to add missing project-local ignore rules for the selected harness
67
+ - Does not exit when all prompts are done; polls for new prompt files instead
68
+ - Serves a kanban board at http://localhost:<port> for visual progress tracking
69
+ - Allows editing prompt files directly from the browser (Trello-style)
70
+ - Play / pause button in the browser stays in sync with the CLI pause state
71
+ - Terminal controls match \`ptbk coder run\`: P pause/resume, S skip waiting, X end after current prompt
72
+ `,
73
+ ),
65
74
  );
66
75
 
67
76
  command.addOption(
@@ -71,11 +80,8 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
71
80
  );
72
81
  command.option('--dry-run', 'Print unwritten prompts without executing', false);
73
82
  addPromptRunnerSelectionOptions(command);
74
- addHarnessUpdateOption(command);
75
- command.option(
76
- '--agent <agent-book-path>',
77
- 'Path to a .book file whose compiled system message is prepended to each coding prompt',
78
- );
83
+ addQuestionsOption(command);
84
+ addCoderAgentOption(command);
79
85
  command.option(
80
86
  '--context <context-or-file>',
81
87
  'Append extra instructions either inline or from a file path relative to the current project',
@@ -160,22 +166,27 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
160
166
  readonly auto: boolean;
161
167
  readonly autoMigrate: boolean;
162
168
  readonly allowDestructiveAutoMigrate: boolean;
163
- } & PromptRunnerCliOptions;
169
+ } & PromptRunnerCliOptions & CoderAgentCliOptions;
164
170
 
165
171
  const port = parseCoderServerPort(rawPort);
166
172
  const testCommand = normalizeCommandOptionValue(test);
167
173
  const runnerOptions = normalizePromptRunnerCliOptions(cliOptions as PromptRunnerCliOptions, {
168
174
  isAgentRequired: !dryRun,
169
175
  });
170
- const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(
171
- cliOptions as HarnessUpdateCliOptions,
172
- );
173
-
174
- await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
175
- await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName);
176
+ const questionsOptions = normalizeQuestionsCliOptions(cliOptions as QuestionsCliOptions);
176
177
 
177
178
  // [1] Parse the wait options and --no-auto (same logic as `coder run`)
178
179
  const waitForUser = !auto;
180
+
181
+ assertUserConfirmationIsAllowed({ ...questionsOptions, isWaitingForUser: waitForUser });
182
+
183
+ // Note: Checked before anything is installed or written, because installing a harness and coding
184
+ // itself both need the disk space which is missing
185
+ await $assertSufficientFreeDiskSpace(process.cwd());
186
+
187
+ await $ensureHarnessInstallations([runnerOptions.agentName], questionsOptions);
188
+ await $ensureCoderHarnessGitignoreRules(process.cwd(), runnerOptions.agentName, questionsOptions);
189
+
179
190
  const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
180
191
  const waitBetweenPrompts = parseOptionalWaitDuration(waitBetweenPromptsValue, 0);
181
192
  const waitAfterError = parseOptionalWaitDuration(waitAfterErrorValue, DEFAULT_WAIT_AFTER_ERROR_MS);
@@ -206,6 +217,7 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
206
217
  allowDestructiveAutoMigrate,
207
218
  autoPush: runnerOptions.autoPush,
208
219
  autoPull: runnerOptions.autoPull,
220
+ isAskingQuestionsEnabled: questionsOptions.isAskingQuestionsEnabled,
209
221
  };
210
222
 
211
223
  // Note: Import dynamically to avoid loading heavy dependencies until needed
@@ -217,8 +229,7 @@ export function $initializeCoderServerCommand(program: Program): $side_effect {
217
229
  await runCodexPromptsServer(runOptions);
218
230
  } catch (error) {
219
231
  assertsError(error);
220
- console.error(colors.bgRed(`${error.name}`));
221
- console.error(colors.red(error.stack || error.message));
232
+ printCoderRunFailure(error);
222
233
  return process.exit(1);
223
234
  }
224
235
 
@@ -1,9 +1,9 @@
1
- import colors from 'colors';
2
1
  import type {
3
2
  Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
4
3
  } from 'commander';
5
4
  import { spaceTrim } from 'spacetrim';
6
5
  import type { $side_effect } from '../../utils/organization/$side_effect';
6
+ import { $requireCliSubcommand } from '../common/$requireCliSubcommand';
7
7
  import { $initializeCoderAddCommand } from './coder/add';
8
8
  import { $initializeCoderFindFreshEmojiTagCommand } from './coder/find-fresh-emoji-tags';
9
9
  import { $initializeCoderFindRefactorCandidatesCommand } from './coder/find-refactor-candidates';
@@ -69,11 +69,7 @@ export function $initializeCoderCommand(program: Program): $side_effect {
69
69
  $initializeCoderFindFreshEmojiTagCommand(coderCommand);
70
70
 
71
71
  // If no subcommand is provided, show help
72
- coderCommand.action(() => {
73
- console.info(colors.yellow('Please specify a subcommand.'));
74
- console.info('');
75
- coderCommand.help();
76
- });
72
+ $requireCliSubcommand(coderCommand);
77
73
  }
78
74
 
79
75
  // Note: [🟡] Code for CLI command [coder](src/cli/cli-commands/coder.ts) should never be published outside of `@promptbook/cli`
@@ -1,15 +1,25 @@
1
1
  import colors from 'colors';
2
2
  import { createInterface } from 'readline';
3
+ import type { NormalizedQuestionsCliOptions } from './questionsCliOptions';
3
4
 
4
5
  /**
5
6
  * Asks the user in the terminal to confirm one optional change.
6
7
  *
7
8
  * Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin.
8
9
  *
9
- * @returns `true` when the user confirms, `false` when the user declines or the terminal is not interactive.
10
+ * @returns `true` when the user confirms, `false` when the user declines, the terminal is not interactive
11
+ * or the questions are disabled by `--no-questions`.
10
12
  * @private internal utility of `promptbookCli`
11
13
  */
12
- export async function $askForConfirmation(question: string): Promise<boolean> {
14
+ export async function $askForConfirmation(
15
+ question: string,
16
+ { isAskingQuestionsEnabled }: NormalizedQuestionsCliOptions,
17
+ ): Promise<boolean> {
18
+ if (!isAskingQuestionsEnabled) {
19
+ // Note: `--no-questions` forbids asking, so the optional change is declined without blocking the run.
20
+ return false;
21
+ }
22
+
13
23
  if (!process.stdin.isTTY) {
14
24
  // Note: In non-interactive environments like CI there is nobody who could confirm the change.
15
25
  return false;
@@ -0,0 +1,35 @@
1
+ import { spaceTrim } from 'spacetrim';
2
+ import { LimitReachedError } from '../../../../errors/LimitReachedError';
3
+ import { $readFreeDiskSpaceStatus } from './$readFreeDiskSpaceStatus';
4
+ import { formatLowFreeDiskSpaceWarning } from './formatLowFreeDiskSpaceWarning';
5
+
6
+ /**
7
+ * Refuses to start one `ptbk coder` command when the disk which hosts the project is nearly full.
8
+ *
9
+ * A run which starts without enough free disk space fails somewhere in the middle, after the coding agent has
10
+ * already rewritten a part of the project, so it is stopped before it writes anything at all.
11
+ *
12
+ * Note: `$` is used to indicate that this function is not a pure function - it reads the state of the filesystem
13
+ *
14
+ * @throws {LimitReachedError} when there is not enough free disk space left to start
15
+ * @private internal utility of `promptbookCli`
16
+ */
17
+ export async function $assertSufficientFreeDiskSpace(inspectedPath: string): Promise<void> {
18
+ const freeDiskSpaceStatus = await $readFreeDiskSpaceStatus(inspectedPath);
19
+
20
+ if (freeDiskSpaceStatus === null || freeDiskSpaceStatus.level === 'sufficient') {
21
+ return;
22
+ }
23
+
24
+ throw new LimitReachedError(
25
+ spaceTrim(
26
+ (block) => `
27
+ There is not enough free disk space to run \`ptbk coder\`.
28
+
29
+ ${block(formatLowFreeDiskSpaceWarning(freeDiskSpaceStatus))}
30
+ `,
31
+ ),
32
+ );
33
+ }
34
+
35
+ // 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`