@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.
- package/esm/index.es.js +1254 -318
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/createFreeDiskSpaceGuard.d.ts +25 -0
- package/esm/scripts/run-codex-prompts/common/formatUnknownErrorDetails.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +21 -3
- package/esm/scripts/run-codex-prompts/main/listCoderPrompts.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +77 -0
- package/esm/scripts/run-codex-prompts/prompts/buildPromptRunTracePath.d.ts +10 -0
- package/esm/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +11 -6
- package/esm/scripts/run-codex-prompts/prompts/loadPromptFiles.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/writePromptRunTrace.d.ts +19 -0
- package/esm/scripts/run-codex-prompts/runners/common/buildHarnessAuthenticationError.d.ts +20 -0
- package/esm/scripts/run-codex-prompts/runners/common/createAuthenticationAwarePromptRunner.d.ts +11 -0
- package/esm/scripts/run-codex-prompts/runners/common/extractHarnessAuthenticationFailureReason.d.ts +9 -0
- package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +3 -0
- package/esm/src/book-2.0/book-language-documentation/getSafeCodeBlock.d.ts +1 -1
- package/esm/src/book-components/Chat/MockedChat/MockedChat.test.d.ts +2 -0
- package/esm/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.d.ts +2 -1
- package/esm/src/cli/cli-commands/coder/agentCliOptions.d.ts +21 -0
- package/esm/src/cli/cli-commands/coder/boilerplateTemplates.d.ts +8 -21
- package/esm/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +33 -0
- package/esm/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +4 -2
- package/esm/src/cli/cli-commands/coder/ensureCoderVscodeSettingsFile.d.ts +2 -0
- package/esm/src/cli/cli-commands/coder/ensureDirectory.d.ts +6 -0
- package/esm/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.d.ts +6 -0
- package/esm/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +7 -5
- package/esm/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +19 -1
- package/esm/src/cli/cli-commands/coder/printCoderRunFailure.d.ts +6 -0
- package/esm/src/cli/cli-commands/common/$askForConfirmation.d.ts +4 -2
- package/esm/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.d.ts +12 -0
- package/esm/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.d.ts +11 -0
- package/esm/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/disk-space/FreeDiskSpaceStatus.d.ts +33 -0
- package/esm/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.d.ts +6 -0
- package/esm/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/disk-space/formatLowFreeDiskSpaceWarning.d.ts +10 -0
- package/esm/src/cli/cli-commands/common/disk-space/freeDiskSpaceConstants.d.ts +28 -0
- package/esm/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.d.ts +7 -0
- package/esm/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.d.ts +2 -1
- package/esm/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -2
- package/esm/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +26 -0
- package/esm/src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.d.ts +4 -2
- package/esm/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +2 -1
- package/esm/src/cli/cli-commands/common/questionsCliOptions.d.ts +45 -0
- package/esm/src/cli/cli-commands/common/questionsCliOptions.test.d.ts +1 -0
- package/esm/src/cli/common/$deprecateCliCommand.d.ts +3 -0
- package/esm/src/cli/common/$hideCliCommandFromHelp.d.ts +11 -0
- package/esm/src/cli/common/$hideCliCommandFromHelp.test.d.ts +1 -0
- package/esm/src/cli/common/$requireCliSubcommand.d.ts +18 -0
- package/esm/src/cli/common/$requireCliSubcommand.test.d.ts +1 -0
- package/esm/src/llm-providers/vercel/VercelExecutionToolsOptions.d.ts +5 -2
- package/esm/src/version.d.ts +1 -1
- package/package.json +8 -11
- package/src/book-2.0/book-language-documentation/getSafeCodeBlock.ts +1 -1
- package/src/book-components/Chat/MockedChat/MockedChat.tsx +25 -1
- package/src/cli/cli-commands/agent-folder.ts +2 -6
- package/src/cli/cli-commands/agent.ts +2 -6
- package/src/cli/cli-commands/agents-server.ts +2 -6
- package/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.ts +3 -0
- package/src/cli/cli-commands/coder/add.ts +27 -2
- package/src/cli/cli-commands/coder/agentCliOptions.ts +32 -0
- package/src/cli/cli-commands/coder/boilerplateTemplates.ts +17 -44
- package/src/cli/cli-commands/coder/coderReferencedArtifacts.ts +106 -0
- package/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.ts +4 -2
- package/src/cli/cli-commands/coder/ensureCoderVscodeSettingsFile.ts +5 -1
- package/src/cli/cli-commands/coder/ensureDirectory.ts +27 -1
- package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +99 -10
- package/src/cli/cli-commands/coder/init.ts +23 -14
- package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +18 -27
- package/src/cli/cli-commands/coder/list.ts +15 -3
- package/src/cli/cli-commands/coder/mergeStringRecordJsonFile.ts +31 -7
- package/src/cli/cli-commands/coder/ping.ts +25 -22
- package/src/cli/cli-commands/coder/printCoderRunFailure.ts +14 -0
- package/src/cli/cli-commands/coder/printInitializationSummary.ts +23 -16
- package/src/cli/cli-commands/coder/run.ts +34 -23
- package/src/cli/cli-commands/coder/server.ts +43 -32
- package/src/cli/cli-commands/coder.ts +2 -6
- package/src/cli/cli-commands/common/$askForConfirmation.ts +12 -2
- package/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.ts +35 -0
- package/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.ts +37 -0
- package/src/cli/cli-commands/common/disk-space/FreeDiskSpaceStatus.ts +39 -0
- package/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.ts +26 -0
- package/src/cli/cli-commands/common/disk-space/formatLowFreeDiskSpaceWarning.ts +33 -0
- package/src/cli/cli-commands/common/disk-space/freeDiskSpaceConstants.ts +33 -0
- package/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.ts +21 -0
- package/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.ts +17 -5
- package/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.ts +8 -3
- package/src/cli/cli-commands/common/harness/HarnessDefinition.ts +36 -0
- package/src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.ts +8 -3
- package/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.ts +13 -2
- package/src/cli/cli-commands/common/questionsCliOptions.ts +89 -0
- package/src/cli/cli-commands/run.ts +3 -1
- package/src/cli/common/$deprecateCliCommand.ts +5 -0
- package/src/cli/common/$hideCliCommandFromHelp.ts +27 -0
- package/src/cli/common/$requireCliSubcommand.ts +35 -0
- package/src/cli/promptbookCli.ts +13 -9
- package/src/llm-providers/vercel/VercelExecutionToolsOptions.ts +7 -2
- package/src/llm-providers/vercel/createExecutionToolsFromVercelProvider.ts +18 -17
- package/src/other/templates/getTemplatesPipelineCollection.ts +677 -881
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +1253 -317
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/createFreeDiskSpaceGuard.d.ts +25 -0
- package/umd/scripts/run-codex-prompts/common/formatUnknownErrorDetails.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +21 -3
- package/umd/scripts/run-codex-prompts/main/listCoderPrompts.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/prompts/buildPromptRunTraceContent.d.ts +77 -0
- package/umd/scripts/run-codex-prompts/prompts/buildPromptRunTracePath.d.ts +10 -0
- package/umd/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +11 -6
- package/umd/scripts/run-codex-prompts/prompts/loadPromptFiles.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/prompts/writePromptRunTrace.d.ts +19 -0
- package/umd/scripts/run-codex-prompts/runners/common/buildHarnessAuthenticationError.d.ts +20 -0
- package/umd/scripts/run-codex-prompts/runners/common/createAuthenticationAwarePromptRunner.d.ts +11 -0
- package/umd/scripts/run-codex-prompts/runners/common/extractHarnessAuthenticationFailureReason.d.ts +9 -0
- package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +3 -0
- package/umd/src/book-2.0/book-language-documentation/getSafeCodeBlock.d.ts +1 -1
- package/umd/src/book-components/Chat/MockedChat/MockedChat.test.d.ts +2 -0
- package/umd/src/cli/cli-commands/coder/$ensureCoderHarnessGitignoreRules.d.ts +2 -1
- package/umd/src/cli/cli-commands/coder/agentCliOptions.d.ts +21 -0
- package/umd/src/cli/cli-commands/coder/boilerplateTemplates.d.ts +8 -21
- package/umd/src/cli/cli-commands/coder/coderReferencedArtifacts.d.ts +33 -0
- package/umd/src/cli/cli-commands/coder/ensureCoderPackageJsonFile.d.ts +4 -2
- package/umd/src/cli/cli-commands/coder/ensureCoderVscodeSettingsFile.d.ts +2 -0
- package/umd/src/cli/cli-commands/coder/ensureDirectory.d.ts +6 -0
- package/umd/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.d.ts +6 -0
- package/umd/src/cli/cli-commands/coder/init.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +7 -5
- package/umd/src/cli/cli-commands/coder/mergeStringRecordJsonFile.d.ts +19 -1
- package/umd/src/cli/cli-commands/coder/printCoderRunFailure.d.ts +6 -0
- package/umd/src/cli/cli-commands/common/$askForConfirmation.d.ts +4 -2
- package/umd/src/cli/cli-commands/common/$askForConfirmation.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.d.ts +12 -0
- package/umd/src/cli/cli-commands/common/disk-space/$assertSufficientFreeDiskSpace.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.d.ts +11 -0
- package/umd/src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/disk-space/FreeDiskSpaceStatus.d.ts +33 -0
- package/umd/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.d.ts +6 -0
- package/umd/src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/disk-space/formatLowFreeDiskSpaceWarning.d.ts +10 -0
- package/umd/src/cli/cli-commands/common/disk-space/freeDiskSpaceConstants.d.ts +28 -0
- package/umd/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.d.ts +7 -0
- package/umd/src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.d.ts +2 -1
- package/umd/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -2
- package/umd/src/cli/cli-commands/common/harness/HarnessDefinition.d.ts +26 -0
- package/umd/src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.d.ts +4 -2
- package/umd/src/cli/cli-commands/common/promptbook-cli/$ensurePromptbookCliInstallations.d.ts +2 -1
- package/umd/src/cli/cli-commands/common/questionsCliOptions.d.ts +45 -0
- package/umd/src/cli/cli-commands/common/questionsCliOptions.test.d.ts +1 -0
- package/umd/src/cli/common/$deprecateCliCommand.d.ts +3 -0
- package/umd/src/cli/common/$hideCliCommandFromHelp.d.ts +11 -0
- package/umd/src/cli/common/$hideCliCommandFromHelp.test.d.ts +1 -0
- package/umd/src/cli/common/$requireCliSubcommand.d.ts +18 -0
- package/umd/src/cli/common/$requireCliSubcommand.test.d.ts +1 -0
- package/umd/src/llm-providers/vercel/VercelExecutionToolsOptions.d.ts +5 -2
- package/umd/src/version.d.ts +1 -1
- package/esm/src/cli/cli-commands/coder/agentCodingFile.d.ts +0 -13
- package/esm/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +0 -29
- package/src/cli/cli-commands/coder/agentCodingFile.ts +0 -25
- package/src/cli/cli-commands/common/harnessUpdateCliOptions.ts +0 -46
- package/umd/src/cli/cli-commands/coder/agentCodingFile.d.ts +0 -13
- package/umd/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +0 -29
- /package/esm/src/cli/cli-commands/{common/harnessUpdateCliOptions.test.d.ts → coder/init.test.d.ts} +0 -0
- /package/{umd/src/cli/cli-commands/common/harnessUpdateCliOptions.test.d.ts → esm/src/cli/cli-commands/common/$askForConfirmation.test.d.ts} +0 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { statfs } from 'fs/promises';
|
|
2
|
+
import type { FreeDiskSpaceStatus } from './FreeDiskSpaceStatus';
|
|
3
|
+
import { resolveFreeDiskSpaceLevel } from './resolveFreeDiskSpaceLevel';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Measures the free disk space on the filesystem which hosts the given path.
|
|
7
|
+
*
|
|
8
|
+
* Note: `$` is used to indicate that this function is not a pure function - it reads the state of the filesystem
|
|
9
|
+
*
|
|
10
|
+
* @returns the measurement, or `null` when the filesystem can not be measured, for example on a platform which
|
|
11
|
+
* does not report filesystem statistics - a run is never stopped by a measurement which could not be taken
|
|
12
|
+
* @private internal utility of `promptbookCli`
|
|
13
|
+
*/
|
|
14
|
+
export async function $readFreeDiskSpaceStatus(inspectedPath: string): Promise<FreeDiskSpaceStatus | null> {
|
|
15
|
+
try {
|
|
16
|
+
const fileSystemStats = await statfs(inspectedPath);
|
|
17
|
+
const blockSizeBytes = fileSystemStats.bsize;
|
|
18
|
+
const availableBytes = fileSystemStats.bavail * blockSizeBytes;
|
|
19
|
+
const totalBytes = fileSystemStats.blocks * blockSizeBytes;
|
|
20
|
+
|
|
21
|
+
if (!Number.isFinite(availableBytes) || availableBytes < 0) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return {
|
|
26
|
+
inspectedPath,
|
|
27
|
+
availableBytes,
|
|
28
|
+
totalBytes,
|
|
29
|
+
level: resolveFreeDiskSpaceLevel(availableBytes),
|
|
30
|
+
};
|
|
31
|
+
} catch {
|
|
32
|
+
// Note: A path or a platform which can not report its free disk space must not stop `ptbk coder` from running
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Note: [🟡] Code for CLI free disk space handling [$readFreeDiskSpaceStatus](src/cli/cli-commands/common/disk-space/$readFreeDiskSpaceStatus.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* How much free disk space is left, measured against the `ptbk coder` free disk space limits.
|
|
3
|
+
*
|
|
4
|
+
* - `sufficient` - there is enough free disk space to start a run and to keep it running
|
|
5
|
+
* - `low` - there is not enough free disk space to start a new run
|
|
6
|
+
* - `critical` - there is not enough free disk space to keep a started run going
|
|
7
|
+
*
|
|
8
|
+
* @private internal utility of `promptbookCli`
|
|
9
|
+
*/
|
|
10
|
+
export type FreeDiskSpaceLevel = 'sufficient' | 'low' | 'critical';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* One measurement of the free disk space on the filesystem which hosts the inspected path.
|
|
14
|
+
*
|
|
15
|
+
* @private internal utility of `promptbookCli`
|
|
16
|
+
*/
|
|
17
|
+
export type FreeDiskSpaceStatus = {
|
|
18
|
+
/**
|
|
19
|
+
* Path whose filesystem was measured.
|
|
20
|
+
*/
|
|
21
|
+
readonly inspectedPath: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Bytes which are still available to the current user on that filesystem.
|
|
25
|
+
*/
|
|
26
|
+
readonly availableBytes: number;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Total size of that filesystem in bytes.
|
|
30
|
+
*/
|
|
31
|
+
readonly totalBytes: number;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Severity of the measured free disk space.
|
|
35
|
+
*/
|
|
36
|
+
readonly level: FreeDiskSpaceLevel;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
// Note: [🟡] Code for CLI free disk space handling [FreeDiskSpaceStatus](src/cli/cli-commands/common/disk-space/FreeDiskSpaceStatus.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Byte units used when one amount of disk space is written for a human.
|
|
3
|
+
*/
|
|
4
|
+
const FREE_DISK_SPACE_BYTE_UNITS = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'] as const;
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Writes one byte count as a compact human-readable amount of disk space, for example `812 MB` or `1.5 GB`.
|
|
8
|
+
*
|
|
9
|
+
* @private internal utility of `promptbookCli`
|
|
10
|
+
*/
|
|
11
|
+
export function formatFreeDiskSpaceBytes(bytes: number): string {
|
|
12
|
+
if (!Number.isFinite(bytes) || bytes <= 0) {
|
|
13
|
+
return '0 B';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const unitIndex = Math.min(FREE_DISK_SPACE_BYTE_UNITS.length - 1, Math.floor(Math.log(bytes) / Math.log(1024)));
|
|
17
|
+
const value = bytes / Math.pow(1024, unitIndex);
|
|
18
|
+
// Note: One decimal place only matters for small values, `476 GB` is more readable than `476.3 GB`
|
|
19
|
+
const decimalPlaceCount = value >= 10 || unitIndex === 0 ? 0 : 1;
|
|
20
|
+
// Note: An empty decimal place only adds noise, `2 GB` is more readable than `2.0 GB`
|
|
21
|
+
const displayedValue = value.toFixed(decimalPlaceCount).replace(/\.0$/, '');
|
|
22
|
+
|
|
23
|
+
return `${displayedValue} ${FREE_DISK_SPACE_BYTE_UNITS[unitIndex]}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Note: [🟡] Code for CLI free disk space handling [formatFreeDiskSpaceBytes](src/cli/cli-commands/common/disk-space/formatFreeDiskSpaceBytes.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { spaceTrim } from 'spacetrim';
|
|
2
|
+
import type { FreeDiskSpaceStatus } from './FreeDiskSpaceStatus';
|
|
3
|
+
import { formatFreeDiskSpaceBytes } from './formatFreeDiskSpaceBytes';
|
|
4
|
+
import { CRITICALLY_LOW_FREE_DISK_SPACE_BYTES, LOW_FREE_DISK_SPACE_BYTES } from './freeDiskSpaceConstants';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Writes the shared warning which explains one low free disk space measurement and how to get out of it.
|
|
8
|
+
*
|
|
9
|
+
* The very same wording is used by the check which refuses to start a run and by the check which pauses
|
|
10
|
+
* a run that ran out of disk space while it was working.
|
|
11
|
+
*
|
|
12
|
+
* @private internal utility of `promptbookCli`
|
|
13
|
+
*/
|
|
14
|
+
export function formatLowFreeDiskSpaceWarning(freeDiskSpaceStatus: FreeDiskSpaceStatus): string {
|
|
15
|
+
const { inspectedPath } = freeDiskSpaceStatus;
|
|
16
|
+
const availableSpace = formatFreeDiskSpaceBytes(freeDiskSpaceStatus.availableBytes);
|
|
17
|
+
const totalSpace = formatFreeDiskSpaceBytes(freeDiskSpaceStatus.totalBytes);
|
|
18
|
+
const requiredSpaceToStart = formatFreeDiskSpaceBytes(LOW_FREE_DISK_SPACE_BYTES);
|
|
19
|
+
const requiredSpaceToContinue = formatFreeDiskSpaceBytes(CRITICALLY_LOW_FREE_DISK_SPACE_BYTES);
|
|
20
|
+
|
|
21
|
+
return spaceTrim(`
|
|
22
|
+
Only **${availableSpace}** of ${totalSpace} is left on the disk which hosts \`${inspectedPath}\`.
|
|
23
|
+
|
|
24
|
+
**\`ptbk coder\` needs at least ${requiredSpaceToStart} of free disk space to start a run and at least ${requiredSpaceToContinue} to keep one running.**
|
|
25
|
+
|
|
26
|
+
Actionable hints:
|
|
27
|
+
- Free up disk space on the drive which hosts \`${inspectedPath}\`.
|
|
28
|
+
- Remove build artifacts, package caches and \`node_modules\` folders of projects you are not working on.
|
|
29
|
+
- Remove the temporary worktrees which earlier \`--isolate\` runs left behind.
|
|
30
|
+
`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Note: [🟡] Code for CLI free disk space handling [formatLowFreeDiskSpaceWarning](src/cli/cli-commands/common/disk-space/formatLowFreeDiskSpaceWarning.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Free disk space below which `ptbk coder` refuses to start a new run.
|
|
3
|
+
*
|
|
4
|
+
* A coding round writes prompt and log artifacts, lets the harness rewrite the project, may install npm packages,
|
|
5
|
+
* may create a git worktree for `--isolate` and usually runs a build, so a run started with less than this
|
|
6
|
+
* would very likely die somewhere in the middle with a filesystem error.
|
|
7
|
+
*
|
|
8
|
+
* @private internal utility of `promptbookCli`
|
|
9
|
+
*/
|
|
10
|
+
export const LOW_FREE_DISK_SPACE_BYTES = 2 * 1024 * 1024 * 1024;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Free disk space below which a started `ptbk coder` run stops at its next checkpoint and waits until space is freed.
|
|
14
|
+
*
|
|
15
|
+
* This limit is lower than `LOW_FREE_DISK_SPACE_BYTES`, because interrupting a run which is already in progress
|
|
16
|
+
* is more expensive than not starting one at all.
|
|
17
|
+
*
|
|
18
|
+
* @private internal utility of `promptbookCli`
|
|
19
|
+
*/
|
|
20
|
+
export const CRITICALLY_LOW_FREE_DISK_SPACE_BYTES = 1 * 1024 * 1024 * 1024;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* How long one free disk space measurement is reused before the filesystem is measured again during a run.
|
|
24
|
+
*
|
|
25
|
+
* Pause checkpoints are passed very often - for example on every tick of a timed wait - so without this
|
|
26
|
+
* interval the filesystem would be measured many times per second.
|
|
27
|
+
*
|
|
28
|
+
* @private internal utility of `promptbookCli`
|
|
29
|
+
*/
|
|
30
|
+
export const FREE_DISK_SPACE_RECHECK_INTERVAL_MS = 60 * 1000;
|
|
31
|
+
|
|
32
|
+
// Note: [🟡] Code for CLI free disk space handling [freeDiskSpaceConstants](src/cli/cli-commands/common/disk-space/freeDiskSpaceConstants.ts) should never be published outside of `@promptbook/cli`
|
|
33
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FreeDiskSpaceLevel } from './FreeDiskSpaceStatus';
|
|
2
|
+
import { CRITICALLY_LOW_FREE_DISK_SPACE_BYTES, LOW_FREE_DISK_SPACE_BYTES } from './freeDiskSpaceConstants';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Classifies one measured amount of free disk space against the `ptbk coder` free disk space limits.
|
|
6
|
+
*
|
|
7
|
+
* @private internal utility of `promptbookCli`
|
|
8
|
+
*/
|
|
9
|
+
export function resolveFreeDiskSpaceLevel(availableBytes: number): FreeDiskSpaceLevel {
|
|
10
|
+
if (availableBytes < CRITICALLY_LOW_FREE_DISK_SPACE_BYTES) {
|
|
11
|
+
return 'critical';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (availableBytes < LOW_FREE_DISK_SPACE_BYTES) {
|
|
15
|
+
return 'low';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return 'sufficient';
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Note: [🟡] Code for CLI free disk space handling [resolveFreeDiskSpaceLevel](src/cli/cli-commands/common/disk-space/resolveFreeDiskSpaceLevel.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import colors from 'colors';
|
|
2
2
|
import { $askForNpmPackageInstallationApproval } from '../npm/$askForNpmPackageInstallationApproval';
|
|
3
|
+
import type { NormalizedQuestionsCliOptions } from '../questionsCliOptions';
|
|
3
4
|
import { $runHarnessInstallationCommand } from './$runHarnessInstallationCommand';
|
|
4
5
|
import { buildHarnessInstallCommand } from './buildHarnessInstallCommand';
|
|
5
6
|
import type { HarnessDefinition } from './HarnessDefinition';
|
|
@@ -15,7 +16,10 @@ import { resolveHarnessUpdatePlan } from './resolveHarnessUpdatePlan';
|
|
|
15
16
|
*
|
|
16
17
|
* @private internal utility of `promptbookCli`
|
|
17
18
|
*/
|
|
18
|
-
export async function $applyHarnessInstallationStatus(
|
|
19
|
+
export async function $applyHarnessInstallationStatus(
|
|
20
|
+
status: HarnessInstallationStatus,
|
|
21
|
+
questionsOptions: NormalizedQuestionsCliOptions,
|
|
22
|
+
): Promise<void> {
|
|
19
23
|
const { definition, installationState, installedVersion } = status;
|
|
20
24
|
|
|
21
25
|
if (installationState === 'up-to-date') {
|
|
@@ -42,21 +46,25 @@ export async function $applyHarnessInstallationStatus(status: HarnessInstallatio
|
|
|
42
46
|
console.warn(colors.yellow(formatHarnessInstallationWarning(status)));
|
|
43
47
|
|
|
44
48
|
if (installationState === 'not-installed') {
|
|
45
|
-
await $applyMissingHarnessInstallation(definition);
|
|
49
|
+
await $applyMissingHarnessInstallation(definition, questionsOptions);
|
|
46
50
|
return;
|
|
47
51
|
}
|
|
48
52
|
|
|
49
|
-
await $applyOutdatedHarnessInstallation(status);
|
|
53
|
+
await $applyOutdatedHarnessInstallation(status, questionsOptions);
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
/**
|
|
53
57
|
* Offers to install a missing harness globally through npm.
|
|
54
58
|
*/
|
|
55
|
-
async function $applyMissingHarnessInstallation(
|
|
59
|
+
async function $applyMissingHarnessInstallation(
|
|
60
|
+
definition: HarnessDefinition,
|
|
61
|
+
questionsOptions: NormalizedQuestionsCliOptions,
|
|
62
|
+
): Promise<void> {
|
|
56
63
|
const installCommand = buildHarnessInstallCommand(definition);
|
|
57
64
|
|
|
58
65
|
const isInstallationApproved = await $askForNpmPackageInstallationApproval(
|
|
59
66
|
`Install ${definition.label} globally now?`,
|
|
67
|
+
questionsOptions,
|
|
60
68
|
);
|
|
61
69
|
|
|
62
70
|
if (!isInstallationApproved) {
|
|
@@ -75,7 +83,10 @@ async function $applyMissingHarnessInstallation(definition: HarnessDefinition):
|
|
|
75
83
|
/**
|
|
76
84
|
* Offers to update an outdated harness exactly where it is installed.
|
|
77
85
|
*/
|
|
78
|
-
async function $applyOutdatedHarnessInstallation(
|
|
86
|
+
async function $applyOutdatedHarnessInstallation(
|
|
87
|
+
status: HarnessInstallationStatus,
|
|
88
|
+
questionsOptions: NormalizedQuestionsCliOptions,
|
|
89
|
+
): Promise<void> {
|
|
79
90
|
const { definition, latestVersion, installationOrigin } = status;
|
|
80
91
|
const updatePlan = resolveHarnessUpdatePlan(definition, installationOrigin.installationMethod);
|
|
81
92
|
|
|
@@ -86,6 +97,7 @@ async function $applyOutdatedHarnessInstallation(status: HarnessInstallationStat
|
|
|
86
97
|
|
|
87
98
|
const isUpdateApproved = await $askForNpmPackageInstallationApproval(
|
|
88
99
|
`Update ${definition.label} to ${latestVersion} with \`${updatePlan.command}\` now?`,
|
|
100
|
+
questionsOptions,
|
|
89
101
|
);
|
|
90
102
|
|
|
91
103
|
if (!isUpdateApproved) {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { PromptRunnerHarnessName } from '../promptRunnerCliOptions';
|
|
2
|
+
import type { NormalizedQuestionsCliOptions } from '../questionsCliOptions';
|
|
2
3
|
import { $applyHarnessInstallationStatus } from './$applyHarnessInstallationStatus';
|
|
3
4
|
import { $checkHarnessInstallation } from './$checkHarnessInstallation';
|
|
4
5
|
import type { HarnessDefinition } from './HarnessDefinition';
|
|
5
6
|
import { getHarnessDefinition } from './HarnessDefinition';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
|
-
* Checks that every given CLI coding harness is installed globally and, when enabled, up to date.
|
|
9
|
+
* Checks that every given CLI coding harness is installed globally and, when the questions are enabled, up to date.
|
|
9
10
|
* Offers to install missing harnesses and update outdated ones.
|
|
10
11
|
*
|
|
11
12
|
* Harness names which are `undefined`, for example when no `--harness` is selected in a dry run,
|
|
@@ -17,7 +18,7 @@ import { getHarnessDefinition } from './HarnessDefinition';
|
|
|
17
18
|
*/
|
|
18
19
|
export async function $ensureHarnessInstallations(
|
|
19
20
|
harnessNames: ReadonlyArray<PromptRunnerHarnessName | undefined>,
|
|
20
|
-
|
|
21
|
+
questionsOptions: NormalizedQuestionsCliOptions,
|
|
21
22
|
): Promise<void> {
|
|
22
23
|
const definitions = resolveCheckedHarnessDefinitions(harnessNames);
|
|
23
24
|
|
|
@@ -25,13 +26,17 @@ export async function $ensureHarnessInstallations(
|
|
|
25
26
|
return;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
// Note: An outdated harness can be updated only after the user confirms it, so `--no-questions`
|
|
30
|
+
// skips the slower npm registry lookup entirely and only reports what is installed.
|
|
31
|
+
const isHarnessUpdateCheckEnabled = questionsOptions.isAskingQuestionsEnabled;
|
|
32
|
+
|
|
28
33
|
// Note: Detection of all harnesses runs in parallel, the questions have to be asked one by one
|
|
29
34
|
const statuses = await Promise.all(
|
|
30
35
|
definitions.map((definition) => $checkHarnessInstallation(definition, isHarnessUpdateCheckEnabled)),
|
|
31
36
|
);
|
|
32
37
|
|
|
33
38
|
for (const status of statuses) {
|
|
34
|
-
await $applyHarnessInstallationStatus(status);
|
|
39
|
+
await $applyHarnessInstallationStatus(status, questionsOptions);
|
|
35
40
|
}
|
|
36
41
|
}
|
|
37
42
|
|
|
@@ -24,6 +24,30 @@ export type HarnessStandaloneInstallation = {
|
|
|
24
24
|
readonly updateCommand: string;
|
|
25
25
|
};
|
|
26
26
|
|
|
27
|
+
/**
|
|
28
|
+
* Description of how the user signs in to one CLI coding harness again.
|
|
29
|
+
*
|
|
30
|
+
* Every harness refuses to work once its login is missing or its session has expired, and each of them is
|
|
31
|
+
* signed in differently - some have a dedicated login command, others sign in from their own interactive UI.
|
|
32
|
+
*
|
|
33
|
+
* @private internal utility of `promptbookCli`
|
|
34
|
+
*/
|
|
35
|
+
export type HarnessAuthenticationMethod = {
|
|
36
|
+
/**
|
|
37
|
+
* Command which starts the sign-in flow of the harness.
|
|
38
|
+
*/
|
|
39
|
+
readonly command: string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Step which finishes the sign-in inside the started command.
|
|
43
|
+
*
|
|
44
|
+
* Harnesses which sign in from their own interactive user interface leave the user in that interface, so
|
|
45
|
+
* naming just the command would not be enough to get them signed in. Harnesses with a dedicated login
|
|
46
|
+
* command leave this undefined.
|
|
47
|
+
*/
|
|
48
|
+
readonly interactiveStep?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
27
51
|
/**
|
|
28
52
|
* Static description of one supported CLI coding harness.
|
|
29
53
|
*
|
|
@@ -60,6 +84,11 @@ export type HarnessDefinition = {
|
|
|
60
84
|
*/
|
|
61
85
|
readonly projectGitignoreRules: ReadonlyArray<string>;
|
|
62
86
|
|
|
87
|
+
/**
|
|
88
|
+
* How the user signs in to this harness again after its login is missing or has expired.
|
|
89
|
+
*/
|
|
90
|
+
readonly authenticationMethod: HarnessAuthenticationMethod;
|
|
91
|
+
|
|
63
92
|
/**
|
|
64
93
|
* How a standalone installation of this harness is recognized and updated.
|
|
65
94
|
*
|
|
@@ -80,6 +109,7 @@ export const HARNESS_DEFINITIONS: Readonly<Record<PromptRunnerHarnessName, Harne
|
|
|
80
109
|
commandName: 'codex',
|
|
81
110
|
npmPackageName: '@openai/codex',
|
|
82
111
|
projectGitignoreRules: ['.codex'],
|
|
112
|
+
authenticationMethod: { command: 'codex login' },
|
|
83
113
|
// Note: The official standalone installer keeps its package in `~/.codex` and links it onto the `PATH`
|
|
84
114
|
standaloneInstallation: {
|
|
85
115
|
directoryNames: ['.codex'],
|
|
@@ -92,6 +122,7 @@ export const HARNESS_DEFINITIONS: Readonly<Record<PromptRunnerHarnessName, Harne
|
|
|
92
122
|
commandName: 'copilot',
|
|
93
123
|
npmPackageName: '@github/copilot',
|
|
94
124
|
projectGitignoreRules: ['.github/copilot/settings.local.json'],
|
|
125
|
+
authenticationMethod: { command: 'copilot', interactiveStep: 'running the `/login` command inside it' },
|
|
95
126
|
// Note: The GitHub Copilot CLI downloads its native binary in a postinstall script
|
|
96
127
|
npmInstallEnvironment: { npm_config_ignore_scripts: 'false' },
|
|
97
128
|
},
|
|
@@ -101,6 +132,7 @@ export const HARNESS_DEFINITIONS: Readonly<Record<PromptRunnerHarnessName, Harne
|
|
|
101
132
|
commandName: 'cline',
|
|
102
133
|
npmPackageName: 'cline',
|
|
103
134
|
projectGitignoreRules: ['.cline'],
|
|
135
|
+
authenticationMethod: { command: 'cline', interactiveStep: 'signing in to the provider inside it' },
|
|
104
136
|
},
|
|
105
137
|
'claude-code': {
|
|
106
138
|
harnessName: 'claude-code',
|
|
@@ -108,6 +140,7 @@ export const HARNESS_DEFINITIONS: Readonly<Record<PromptRunnerHarnessName, Harne
|
|
|
108
140
|
commandName: 'claude',
|
|
109
141
|
npmPackageName: '@anthropic-ai/claude-code',
|
|
110
142
|
projectGitignoreRules: ['.claude'],
|
|
143
|
+
authenticationMethod: { command: 'claude', interactiveStep: 'running the `/login` command inside it' },
|
|
111
144
|
},
|
|
112
145
|
opencode: {
|
|
113
146
|
harnessName: 'opencode',
|
|
@@ -115,6 +148,7 @@ export const HARNESS_DEFINITIONS: Readonly<Record<PromptRunnerHarnessName, Harne
|
|
|
115
148
|
commandName: 'opencode',
|
|
116
149
|
npmPackageName: 'opencode-ai',
|
|
117
150
|
projectGitignoreRules: ['.opencode'],
|
|
151
|
+
authenticationMethod: { command: 'opencode auth login' },
|
|
118
152
|
},
|
|
119
153
|
gemini: {
|
|
120
154
|
harnessName: 'gemini',
|
|
@@ -122,6 +156,7 @@ export const HARNESS_DEFINITIONS: Readonly<Record<PromptRunnerHarnessName, Harne
|
|
|
122
156
|
commandName: 'gemini',
|
|
123
157
|
npmPackageName: '@google/gemini-cli',
|
|
124
158
|
projectGitignoreRules: ['.gemini'],
|
|
159
|
+
authenticationMethod: { command: 'gemini', interactiveStep: 'running the `/auth` command inside it' },
|
|
125
160
|
},
|
|
126
161
|
'qwen-code': {
|
|
127
162
|
harnessName: 'qwen-code',
|
|
@@ -129,6 +164,7 @@ export const HARNESS_DEFINITIONS: Readonly<Record<PromptRunnerHarnessName, Harne
|
|
|
129
164
|
commandName: 'qwen',
|
|
130
165
|
npmPackageName: '@qwen-code/qwen-code',
|
|
131
166
|
projectGitignoreRules: ['.qwen'],
|
|
167
|
+
authenticationMethod: { command: 'qwen', interactiveStep: 'running the `/auth` command inside it' },
|
|
132
168
|
},
|
|
133
169
|
};
|
|
134
170
|
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { $askForConfirmation } from '../$askForConfirmation';
|
|
2
|
+
import type { NormalizedQuestionsCliOptions } from '../questionsCliOptions';
|
|
2
3
|
|
|
3
4
|
/**
|
|
4
5
|
* Asks the user in the terminal whether an npm package should be installed or updated now.
|
|
5
6
|
*
|
|
6
7
|
* Note: `$` is used to indicate that this function is not a pure function - it reads the answer from stdin
|
|
7
8
|
*
|
|
8
|
-
* @returns `true` when the user confirms, `false` when the user declines
|
|
9
|
+
* @returns `true` when the user confirms, `false` when the user declines, the terminal is not interactive
|
|
10
|
+
* or the questions are disabled by `--no-questions`
|
|
9
11
|
* @private internal utility of `promptbookCli`
|
|
10
12
|
*/
|
|
11
|
-
export async function $askForNpmPackageInstallationApproval(
|
|
12
|
-
|
|
13
|
+
export async function $askForNpmPackageInstallationApproval(
|
|
14
|
+
question: string,
|
|
15
|
+
questionsOptions: NormalizedQuestionsCliOptions,
|
|
16
|
+
): Promise<boolean> {
|
|
17
|
+
return $askForConfirmation(question, questionsOptions);
|
|
13
18
|
}
|
|
14
19
|
|
|
15
20
|
// Note: [🟡] Code for CLI npm package installation approval [$askForNpmPackageInstallationApproval](src/cli/cli-commands/common/npm/$askForNpmPackageInstallationApproval.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import colors from 'colors';
|
|
2
2
|
import { spaceTrim } from 'spacetrim';
|
|
3
3
|
import { $askForNpmPackageInstallationApproval } from '../npm/$askForNpmPackageInstallationApproval';
|
|
4
|
+
import type { NormalizedQuestionsCliOptions } from '../questionsCliOptions';
|
|
4
5
|
import { $checkPromptbookCliInstallations } from './$checkPromptbookCliInstallations';
|
|
5
6
|
import { $updatePromptbookCliInstallation } from './$updatePromptbookCliInstallation';
|
|
6
7
|
import { buildPromptbookCliInstallCommand } from './buildPromptbookCliInstallCommand';
|
|
@@ -20,7 +21,14 @@ import { formatPromptbookCliInstallationWarning } from './formatPromptbookCliIns
|
|
|
20
21
|
* @returns `true` when at least one installation was updated and the current coder run should stop
|
|
21
22
|
* @private internal utility of `promptbookCli`
|
|
22
23
|
*/
|
|
23
|
-
export async function $ensurePromptbookCliInstallations(
|
|
24
|
+
export async function $ensurePromptbookCliInstallations(
|
|
25
|
+
questionsOptions: NormalizedQuestionsCliOptions,
|
|
26
|
+
): Promise<boolean> {
|
|
27
|
+
if (!questionsOptions.isAskingQuestionsEnabled) {
|
|
28
|
+
// Note: `--no-questions` forbids asking for the approval, so the registry checks would be useless
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
|
|
24
32
|
if (!process.stdin.isTTY) {
|
|
25
33
|
// Note: Non-interactive runs cannot approve an update and should not wait for registry checks
|
|
26
34
|
return false;
|
|
@@ -36,7 +44,10 @@ export async function $ensurePromptbookCliInstallations(): Promise<boolean> {
|
|
|
36
44
|
|
|
37
45
|
console.warn(colors.yellow(formatPromptbookCliInstallationWarning(outdatedStatuses)));
|
|
38
46
|
|
|
39
|
-
const isUpdateApproved = await $askForNpmPackageInstallationApproval(
|
|
47
|
+
const isUpdateApproved = await $askForNpmPackageInstallationApproval(
|
|
48
|
+
'Update Promptbook CLI now?',
|
|
49
|
+
questionsOptions,
|
|
50
|
+
);
|
|
40
51
|
|
|
41
52
|
if (!isUpdateApproved) {
|
|
42
53
|
reportManualPromptbookCliUpdateCommands(outdatedStatuses);
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */,
|
|
3
|
+
} from 'commander';
|
|
4
|
+
import { spaceTrim } from 'spacetrim';
|
|
5
|
+
import { NotAllowed } from '../../../errors/NotAllowed';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Commander option bag for opting out of every interactive question.
|
|
9
|
+
*
|
|
10
|
+
* @private internal utility of `promptbookCli`
|
|
11
|
+
*/
|
|
12
|
+
export type QuestionsCliOptions = {
|
|
13
|
+
readonly questions: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Normalized interactive-questions option shared by every `ptbk coder` command which can ask something.
|
|
18
|
+
*
|
|
19
|
+
* @private internal utility of `promptbookCli`
|
|
20
|
+
*/
|
|
21
|
+
export type NormalizedQuestionsCliOptions = {
|
|
22
|
+
readonly isAskingQuestionsEnabled: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Description block shared by the `ptbk coder` commands which can ask interactive questions.
|
|
27
|
+
*
|
|
28
|
+
* @private internal utility of `promptbookCli`
|
|
29
|
+
*/
|
|
30
|
+
export const QUESTIONS_DESCRIPTION = spaceTrim(`
|
|
31
|
+
Interactive questions:
|
|
32
|
+
- Steps which need an answer to continue are asked in the terminal
|
|
33
|
+
- --no-questions never asks: an optional step is skipped with a note how to do it manually, a required one fails right away
|
|
34
|
+
`);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Registers the shared `--no-questions` option on a `ptbk coder` command which can ask interactive questions.
|
|
38
|
+
*
|
|
39
|
+
* @private internal utility of `promptbookCli`
|
|
40
|
+
*/
|
|
41
|
+
export function addQuestionsOption(command: Program): void {
|
|
42
|
+
command.option(
|
|
43
|
+
'--no-questions',
|
|
44
|
+
'Never ask an interactive question and skip every optional step which needs an answer to continue',
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Converts the Commander questions flag into the normalized interactive-questions option.
|
|
50
|
+
*
|
|
51
|
+
* @private internal utility of `promptbookCli`
|
|
52
|
+
*/
|
|
53
|
+
export function normalizeQuestionsCliOptions(cliOptions: QuestionsCliOptions): NormalizedQuestionsCliOptions {
|
|
54
|
+
return {
|
|
55
|
+
isAskingQuestionsEnabled: cliOptions.questions,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Asserts that a command which waits for a user confirmation before each prompt is allowed to ask for it.
|
|
61
|
+
*
|
|
62
|
+
* @throws {NotAllowed} when `--no-auto` is combined with `--no-questions`
|
|
63
|
+
* @private internal utility of `promptbookCli`
|
|
64
|
+
*/
|
|
65
|
+
export function assertUserConfirmationIsAllowed(options: {
|
|
66
|
+
readonly isAskingQuestionsEnabled: boolean;
|
|
67
|
+
readonly isWaitingForUser: boolean;
|
|
68
|
+
}): void {
|
|
69
|
+
const { isAskingQuestionsEnabled, isWaitingForUser } = options;
|
|
70
|
+
|
|
71
|
+
if (!isWaitingForUser || isAskingQuestionsEnabled) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
throw new NotAllowed(
|
|
76
|
+
spaceTrim(`
|
|
77
|
+
Flag \`--no-auto\` can not be used together with \`--no-questions\`.
|
|
78
|
+
|
|
79
|
+
**There is nobody who could confirm each prompt when no question may be asked.**
|
|
80
|
+
|
|
81
|
+
Actionable hints:
|
|
82
|
+
- Keep \`--no-auto\` for a supervised run, for example \`ptbk coder run --harness claude-code --no-auto\`.
|
|
83
|
+
- Keep \`--no-questions\` for an unattended run, for example \`ptbk coder run --harness claude-code --no-questions\`.
|
|
84
|
+
`),
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Note: [🟡] Code for CLI interactive questions options [questionsCliOptions](src/cli/cli-commands/common/questionsCliOptions.ts) should never be published outside of `@promptbook/cli`
|
|
89
|
+
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
@@ -13,7 +13,9 @@ import type { RunCommandCliOptions } from './run/runCommandAction';
|
|
|
13
13
|
* @private internal function of `promptbookCli`
|
|
14
14
|
*/
|
|
15
15
|
export function $initializeRunCommand(program: Program): $side_effect {
|
|
16
|
-
|
|
16
|
+
// Note: `run` is deprecated, so it is intentionally NOT the default command of `ptbk`
|
|
17
|
+
// and it must be asked for explicitly
|
|
18
|
+
const runCommand = program.command('run');
|
|
17
19
|
|
|
18
20
|
configureRunCommand(runCommand);
|
|
19
21
|
runCommand.action(
|
|
@@ -2,10 +2,14 @@ import colors from 'colors';
|
|
|
2
2
|
import { Command } from 'commander';
|
|
3
3
|
import { spaceTrim } from 'spacetrim';
|
|
4
4
|
import type { $side_effect } from '../../utils/organization/$side_effect';
|
|
5
|
+
import { $hideCliCommandFromHelp } from './$hideCliCommandFromHelp';
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Marks one CLI command as deprecated while keeping it available for existing callers.
|
|
8
9
|
*
|
|
10
|
+
* Deprecated commands are not advertised anymore - they are hidden from the list of commands in the help of their
|
|
11
|
+
* parent command, they warn when they are used and they explain the deprecation in their own help.
|
|
12
|
+
*
|
|
9
13
|
* @private utility of CLI
|
|
10
14
|
*/
|
|
11
15
|
export function $deprecateCliCommand(command: Command, deprecationMessage: string): $side_effect {
|
|
@@ -21,6 +25,7 @@ export function $deprecateCliCommand(command: Command, deprecationMessage: strin
|
|
|
21
25
|
command.hook('preAction', () => {
|
|
22
26
|
console.warn(colors.yellow(createDeprecatedCliCommandWarning(command, deprecationMessage)));
|
|
23
27
|
});
|
|
28
|
+
$hideCliCommandFromHelp(command);
|
|
24
29
|
}
|
|
25
30
|
|
|
26
31
|
/**
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
import type { $side_effect } from '../../utils/organization/$side_effect';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Shape of the Commander internals which decide whether one command is listed among the subcommands in the help
|
|
6
|
+
*
|
|
7
|
+
* Note: Commander accepts hiding only while the command is being registered - `program.command(name, { hidden: true })`
|
|
8
|
+
* or `program.addCommand(command, { hidden: true })` - and exposes no setter for an already registered command,
|
|
9
|
+
* so the very same flag which both of them set is written here directly.
|
|
10
|
+
*
|
|
11
|
+
* @private internal type of `$hideCliCommandFromHelp`
|
|
12
|
+
*/
|
|
13
|
+
type CommandWithHiddenFlag = {
|
|
14
|
+
_hidden: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Keeps one already registered CLI command out of the help of its parent command while the command itself stays
|
|
19
|
+
* fully usable - it can still be run, it still has its own help and it is still reachable through `ptbk help <command>`.
|
|
20
|
+
*
|
|
21
|
+
* Note: `$` is used to indicate that this function is not a pure function - it changes how the CLI renders its help
|
|
22
|
+
*
|
|
23
|
+
* @private utility of CLI
|
|
24
|
+
*/
|
|
25
|
+
export function $hideCliCommandFromHelp(command: Command): $side_effect {
|
|
26
|
+
(command as unknown as CommandWithHiddenFlag)._hidden = true;
|
|
27
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import type { Command } from 'commander';
|
|
3
|
+
import type { $side_effect } from '../../utils/organization/$side_effect';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Message printed when one CLI command which only groups subcommands is run without picking any of them.
|
|
7
|
+
*
|
|
8
|
+
* @private internal constant of `$requireCliSubcommand`
|
|
9
|
+
*/
|
|
10
|
+
const MISSING_CLI_SUBCOMMAND_MESSAGE = 'Please specify a subcommand.';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Makes one CLI command which only groups subcommands ask for a subcommand instead of doing anything on its own.
|
|
14
|
+
*
|
|
15
|
+
* Note: `$` is used to indicate that this function is not a pure function - it registers an action in the CLI
|
|
16
|
+
*
|
|
17
|
+
* @private utility of CLI
|
|
18
|
+
*/
|
|
19
|
+
export function $requireCliSubcommand(command: Command): $side_effect {
|
|
20
|
+
command.action(() => $reportMissingCliSubcommand(command));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Asks for a subcommand of one CLI command, prints its help and exits the process.
|
|
25
|
+
*
|
|
26
|
+
* Note: `$` is used to indicate that this function is not a pure function - it writes to the console and exits the process
|
|
27
|
+
*
|
|
28
|
+
* @private utility of CLI
|
|
29
|
+
*/
|
|
30
|
+
export function $reportMissingCliSubcommand(command: Command): never {
|
|
31
|
+
console.info(colors.yellow(MISSING_CLI_SUBCOMMAND_MESSAGE));
|
|
32
|
+
console.info('');
|
|
33
|
+
|
|
34
|
+
return command.help();
|
|
35
|
+
}
|