@promptbook/cli 0.112.0-41 → 0.112.0-42
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/apps/agents-server/src/database/acquireMigrationExecutionLock.d.ts +12 -1
- package/esm/apps/agents-server/src/database/runDatabaseMigrations.d.ts +9 -0
- package/esm/index.es.js +189 -29
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/verify-prompts/verify-prompts.d.ts +23 -2
- package/esm/src/cli/cli-commands/coder/verify.test.d.ts +1 -0
- package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +2 -14
- package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.d.ts +40 -0
- package/esm/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/apps/agents-server/src/database/acquireMigrationExecutionLock.d.ts +12 -1
- package/umd/apps/agents-server/src/database/runDatabaseMigrations.d.ts +9 -0
- package/umd/index.umd.js +189 -29
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/verify-prompts/verify-prompts.d.ts +23 -2
- package/umd/src/cli/cli-commands/coder/verify.test.d.ts +1 -0
- package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/AgentCollectionInSupabase.d.ts +2 -14
- package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.d.ts +40 -0
- package/umd/src/collection/agent-collection/constructors/agent-collection-in-supabase/createAgentPersistenceRecords.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -1,8 +1,29 @@
|
|
|
1
|
+
import type { PromptFile } from '../run-codex-prompts/prompts/types/PromptFile';
|
|
2
|
+
/**
|
|
3
|
+
* Options supported by the prompt verification helper.
|
|
4
|
+
*/
|
|
5
|
+
export type VerifyPromptsOptions = {
|
|
6
|
+
/**
|
|
7
|
+
* Process prompt files in reverse order.
|
|
8
|
+
*/
|
|
9
|
+
readonly reverse?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Ignore prompt files whose filename or first prompt line contains one of the provided values.
|
|
12
|
+
*/
|
|
13
|
+
readonly ignore?: ReadonlyArray<string>;
|
|
14
|
+
};
|
|
1
15
|
/**
|
|
2
16
|
* Starts the verification loop and exits when no `[ ]` prompts remain.
|
|
3
17
|
*
|
|
4
|
-
* @
|
|
18
|
+
* @public exported from `@promptbook/cli`
|
|
19
|
+
*/
|
|
20
|
+
export declare function verifyPrompts(options?: VerifyPromptsOptions): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Splits prompt files into files that should be verified now and files ignored for this run.
|
|
5
23
|
*
|
|
6
24
|
* @public exported from `@promptbook/cli`
|
|
7
25
|
*/
|
|
8
|
-
export declare function
|
|
26
|
+
export declare function partitionPromptFilesByIgnore(promptFiles: ReadonlyArray<PromptFile>, ignoreValues: ReadonlyArray<string>): {
|
|
27
|
+
promptFiles: PromptFile[];
|
|
28
|
+
ignoredPromptFiles: PromptFile[];
|
|
29
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,23 +4,11 @@ import type { string_book } from '../../../../book-2.0/agent-source/string_book'
|
|
|
4
4
|
import type { string_agent_name, string_agent_permanent_id } from '../../../../types/typeAliases';
|
|
5
5
|
import { AgentCollectionInSupabaseOptions } from './AgentCollectionInSupabaseOptions';
|
|
6
6
|
import type { AgentsDatabaseSchema } from './AgentsDatabaseSchema';
|
|
7
|
+
import { type CreateAgentPersistenceRecordsOptions } from './createAgentPersistenceRecords';
|
|
7
8
|
/**
|
|
8
9
|
* Options for creating a new agent entry.
|
|
9
10
|
*/
|
|
10
|
-
type CreateAgentOptions =
|
|
11
|
-
/**
|
|
12
|
-
* Visibility for the new agent.
|
|
13
|
-
*/
|
|
14
|
-
readonly visibility?: 'PRIVATE' | 'UNLISTED' | 'PUBLIC';
|
|
15
|
-
/**
|
|
16
|
-
* Folder identifier to assign the new agent to.
|
|
17
|
-
*/
|
|
18
|
-
readonly folderId?: number | null;
|
|
19
|
-
/**
|
|
20
|
-
* Sort order for the agent within its parent folder.
|
|
21
|
-
*/
|
|
22
|
-
readonly sortOrder?: number;
|
|
23
|
-
};
|
|
11
|
+
type CreateAgentOptions = CreateAgentPersistenceRecordsOptions;
|
|
24
12
|
/**
|
|
25
13
|
* Optional controls for persisting one source update.
|
|
26
14
|
*/
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { AgentBasicInformation } from '../../../../book-2.0/agent-source/AgentBasicInformation';
|
|
2
|
+
import type { string_book } from '../../../../book-2.0/agent-source/string_book';
|
|
3
|
+
import type { CreateAgentInput } from '../../CreateAgentInput';
|
|
4
|
+
import type { AgentsDatabaseSchema } from './AgentsDatabaseSchema';
|
|
5
|
+
/**
|
|
6
|
+
* Optional persistence overrides for one new agent row.
|
|
7
|
+
*
|
|
8
|
+
* @private shared persistence helper for `AgentCollectionInSupabase`
|
|
9
|
+
*/
|
|
10
|
+
export type CreateAgentPersistenceRecordsOptions = Omit<CreateAgentInput, 'source'>;
|
|
11
|
+
/**
|
|
12
|
+
* Prepared insert rows and returned profile for one newly persisted agent.
|
|
13
|
+
*
|
|
14
|
+
* @private shared persistence helper for `AgentCollectionInSupabase`
|
|
15
|
+
*/
|
|
16
|
+
export type CreateAgentPersistenceRecordsResult = {
|
|
17
|
+
/**
|
|
18
|
+
* Parsed created agent profile including the resolved permanent id.
|
|
19
|
+
*/
|
|
20
|
+
readonly createdAgent: AgentBasicInformation & Required<Pick<AgentBasicInformation, 'permanentId'>>;
|
|
21
|
+
/**
|
|
22
|
+
* Insert row for the `Agent` table.
|
|
23
|
+
*/
|
|
24
|
+
readonly agentInsertRecord: AgentsDatabaseSchema['public']['Tables']['Agent']['Insert'];
|
|
25
|
+
/**
|
|
26
|
+
* Insert row for the `AgentHistory` table.
|
|
27
|
+
*/
|
|
28
|
+
readonly agentHistoryInsertRecord: AgentsDatabaseSchema['public']['Tables']['AgentHistory']['Insert'];
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Builds normalized insert rows for a newly created persisted agent.
|
|
32
|
+
*
|
|
33
|
+
* @param agentSource - Source content of the agent.
|
|
34
|
+
* @param options - Optional folder placement, ordering, and visibility overrides.
|
|
35
|
+
* @param createdAt - Shared creation timestamp used across all persisted rows.
|
|
36
|
+
* @returns Insert rows and the created agent profile.
|
|
37
|
+
*
|
|
38
|
+
* @private shared persistence helper for `AgentCollectionInSupabase`
|
|
39
|
+
*/
|
|
40
|
+
export declare function createAgentPersistenceRecords(agentSource: string_book, options?: CreateAgentPersistenceRecordsOptions, createdAt?: string): CreateAgentPersistenceRecordsResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/esm/src/version.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
|
|
|
15
15
|
export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
|
|
16
16
|
/**
|
|
17
17
|
* Represents the version string of the Promptbook engine.
|
|
18
|
-
* It follows semantic versioning (e.g., `0.112.0-
|
|
18
|
+
* It follows semantic versioning (e.g., `0.112.0-41`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/package.json
CHANGED
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import type { Client } from 'pg';
|
|
2
2
|
import type { DatabaseMigrationLogger } from './runDatabaseMigrations';
|
|
3
|
+
/**
|
|
4
|
+
* Lock-acquisition strategies used by the migration runner.
|
|
5
|
+
*
|
|
6
|
+
* `wait` is appropriate for explicit/manual migration flows where the caller expects one serialized run.
|
|
7
|
+
* `skip` is appropriate for background startup checks where waiting would block request handling.
|
|
8
|
+
*
|
|
9
|
+
* @private function of runDatabaseMigrations
|
|
10
|
+
*/
|
|
11
|
+
export type DatabaseMigrationExecutionLockMode = 'wait' | 'skip';
|
|
3
12
|
/**
|
|
4
13
|
* Acquires advisory lock preventing concurrent migration execution across processes.
|
|
5
14
|
*
|
|
6
15
|
* @param client Connected PostgreSQL client.
|
|
7
16
|
* @param logger Logger used for progress output.
|
|
17
|
+
* @param mode Whether the caller should block for the lock or skip when it is already held.
|
|
18
|
+
* @returns `true` when the lock was acquired and migrations may proceed.
|
|
8
19
|
*
|
|
9
20
|
* @private function of runDatabaseMigrations
|
|
10
21
|
*/
|
|
11
|
-
export declare function acquireMigrationExecutionLock(client: Client, logger: DatabaseMigrationLogger): Promise<
|
|
22
|
+
export declare function acquireMigrationExecutionLock(client: Client, logger: DatabaseMigrationLogger, mode?: DatabaseMigrationExecutionLockMode): Promise<boolean>;
|
|
12
23
|
/**
|
|
13
24
|
* Releases advisory lock used for migration execution.
|
|
14
25
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ServerRecord } from '../utils/serverRegistry';
|
|
2
|
+
import { type DatabaseMigrationExecutionLockMode } from './acquireMigrationExecutionLock';
|
|
2
3
|
/**
|
|
3
4
|
* Allowed values describing who applied a migration record.
|
|
4
5
|
*/
|
|
@@ -67,6 +68,10 @@ export type RunDatabaseMigrationsOptions = {
|
|
|
67
68
|
* If true, prints every SQL migration body before execution.
|
|
68
69
|
*/
|
|
69
70
|
readonly logSqlStatements?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Whether migration execution should wait for the advisory lock or skip when another process already owns it.
|
|
73
|
+
*/
|
|
74
|
+
readonly executionLockMode?: DatabaseMigrationExecutionLockMode;
|
|
70
75
|
};
|
|
71
76
|
/**
|
|
72
77
|
* Result of one prefix migration run.
|
|
@@ -97,6 +102,10 @@ export type RunDatabaseMigrationsResult = {
|
|
|
97
102
|
* Per-prefix summary.
|
|
98
103
|
*/
|
|
99
104
|
readonly perPrefix: ReadonlyArray<DatabaseMigrationPrefixResult>;
|
|
105
|
+
/**
|
|
106
|
+
* Whether migration execution was skipped because another process already held the advisory lock.
|
|
107
|
+
*/
|
|
108
|
+
readonly isSkippedDueToActiveMigrationLock: boolean;
|
|
100
109
|
};
|
|
101
110
|
/**
|
|
102
111
|
* Reads migration runtime configuration from environment variables and `_Server`.
|
package/umd/index.umd.js
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
* @generated
|
|
61
61
|
* @see https://github.com/webgptorg/promptbook
|
|
62
62
|
*/
|
|
63
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
63
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-42';
|
|
64
64
|
/**
|
|
65
65
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
66
66
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -3094,14 +3094,16 @@
|
|
|
3094
3094
|
- Archives verified prompt files to prompts/done/ directory
|
|
3095
3095
|
- Auto-appends repair prompts for incomplete work
|
|
3096
3096
|
- Processes files with all-done prompts first
|
|
3097
|
+
- Supports ignoring matching prompt candidates for one verification run
|
|
3097
3098
|
`));
|
|
3098
3099
|
command.option('--reverse', 'Process prompt files in reverse order', false);
|
|
3100
|
+
command.option('--ignore <candidate-text>', 'Ignore prompt files whose filename or first prompt line contains the given text (repeatable)', collectStringOption, []);
|
|
3099
3101
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
3100
|
-
const { reverse } = cliOptions;
|
|
3102
|
+
const { reverse, ignore } = cliOptions;
|
|
3101
3103
|
// Note: Import the main function dynamically to avoid loading heavy dependencies until needed
|
|
3102
3104
|
const { verifyPrompts } = await Promise.resolve().then(function () { return verifyPrompts$1; });
|
|
3103
3105
|
try {
|
|
3104
|
-
await verifyPrompts(reverse);
|
|
3106
|
+
await verifyPrompts({ reverse, ignore });
|
|
3105
3107
|
}
|
|
3106
3108
|
catch (error) {
|
|
3107
3109
|
console.error(colors__default["default"].bgRed('Prompt verification failed:'), error);
|
|
@@ -3110,6 +3112,14 @@
|
|
|
3110
3112
|
return process.exit(0);
|
|
3111
3113
|
}));
|
|
3112
3114
|
}
|
|
3115
|
+
/**
|
|
3116
|
+
* Collects repeatable string options from Commander.
|
|
3117
|
+
*
|
|
3118
|
+
* @private internal utility of `coder verify` command
|
|
3119
|
+
*/
|
|
3120
|
+
function collectStringOption(value, previousValues) {
|
|
3121
|
+
return [...previousValues, value];
|
|
3122
|
+
}
|
|
3113
3123
|
// Note: [🟡] Code for CLI command [verify](src/cli/cli-commands/coder/verify.ts) should never be published outside of `@promptbook/cli`
|
|
3114
3124
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3115
3125
|
|
|
@@ -45392,6 +45402,7 @@
|
|
|
45392
45402
|
return value.split('\\').join('/');
|
|
45393
45403
|
}
|
|
45394
45404
|
|
|
45405
|
+
// cspell:ignore hashtext
|
|
45395
45406
|
/**
|
|
45396
45407
|
* Cross-process advisory lock key guarding migration execution.
|
|
45397
45408
|
*
|
|
@@ -45403,13 +45414,27 @@
|
|
|
45403
45414
|
*
|
|
45404
45415
|
* @param client Connected PostgreSQL client.
|
|
45405
45416
|
* @param logger Logger used for progress output.
|
|
45417
|
+
* @param mode Whether the caller should block for the lock or skip when it is already held.
|
|
45418
|
+
* @returns `true` when the lock was acquired and migrations may proceed.
|
|
45406
45419
|
*
|
|
45407
45420
|
* @private function of runDatabaseMigrations
|
|
45408
45421
|
*/
|
|
45409
|
-
async function acquireMigrationExecutionLock(client, logger) {
|
|
45422
|
+
async function acquireMigrationExecutionLock(client, logger, mode = 'wait') {
|
|
45423
|
+
var _a;
|
|
45424
|
+
if (mode === 'skip') {
|
|
45425
|
+
logger.info('🔒 Checking migration lock without waiting');
|
|
45426
|
+
const { rows } = await client.query('SELECT pg_try_advisory_lock(hashtext($1)) AS "isMigrationLockAcquired";', [DATABASE_MIGRATION_LOCK_KEY]);
|
|
45427
|
+
if (!((_a = rows[0]) === null || _a === void 0 ? void 0 : _a.isMigrationLockAcquired)) {
|
|
45428
|
+
logger.info('⏭️ Migration lock is already held by another process. Skipping this migration attempt.');
|
|
45429
|
+
return false;
|
|
45430
|
+
}
|
|
45431
|
+
logger.info('🔒 Migration lock acquired');
|
|
45432
|
+
return true;
|
|
45433
|
+
}
|
|
45410
45434
|
logger.info('🔒 Waiting for migration lock');
|
|
45411
45435
|
await client.query('SELECT pg_advisory_lock(hashtext($1));', [DATABASE_MIGRATION_LOCK_KEY]);
|
|
45412
45436
|
logger.info('🔒 Migration lock acquired');
|
|
45437
|
+
return true;
|
|
45413
45438
|
}
|
|
45414
45439
|
/**
|
|
45415
45440
|
* Releases advisory lock used for migration execution.
|
|
@@ -45933,23 +45958,33 @@
|
|
|
45933
45958
|
* @returns Aggregated migration summary.
|
|
45934
45959
|
*/
|
|
45935
45960
|
async function runDatabaseMigrations(options) {
|
|
45936
|
-
var _a, _b, _c, _d;
|
|
45961
|
+
var _a, _b, _c, _d, _e;
|
|
45937
45962
|
const logger = (_a = options.logger) !== null && _a !== void 0 ? _a : console;
|
|
45938
45963
|
const selectedPrefixes = selectPrefixesForMigration(options.prefixes, (_b = options.registeredServers) !== null && _b !== void 0 ? _b : [], options.onlyTargets);
|
|
45939
45964
|
const migrationsDirectory = (_c = options.migrationsDirectory) !== null && _c !== void 0 ? _c : (await resolveMigrationsDirectory());
|
|
45940
45965
|
const migrationFiles = await readMigrationFiles(migrationsDirectory);
|
|
45966
|
+
const totalMigrationFiles = migrationFiles.length;
|
|
45941
45967
|
const perPrefix = [];
|
|
45942
|
-
logger.info(`📂 Found ${
|
|
45968
|
+
logger.info(`📂 Found ${totalMigrationFiles} migration files`);
|
|
45943
45969
|
logger.info(`📋 Found ${selectedPrefixes.length} prefixes to migrate: ${selectedPrefixes
|
|
45944
45970
|
.map((prefix) => prefix || '<default>')
|
|
45945
45971
|
.join(', ')}`);
|
|
45946
45972
|
const client = await createPostgresClient(options.connectionString);
|
|
45947
45973
|
let hasExecutionLock = false;
|
|
45974
|
+
let isSkippedDueToActiveMigrationLock = false;
|
|
45948
45975
|
try {
|
|
45949
45976
|
await client.connect();
|
|
45950
45977
|
logger.info('🔌 Connected to database');
|
|
45951
|
-
await acquireMigrationExecutionLock(client, logger);
|
|
45952
|
-
hasExecutionLock
|
|
45978
|
+
hasExecutionLock = await acquireMigrationExecutionLock(client, logger, (_d = options.executionLockMode) !== null && _d !== void 0 ? _d : 'wait');
|
|
45979
|
+
if (!hasExecutionLock) {
|
|
45980
|
+
isSkippedDueToActiveMigrationLock = true;
|
|
45981
|
+
return {
|
|
45982
|
+
processedPrefixes: [],
|
|
45983
|
+
totalMigrationFiles,
|
|
45984
|
+
perPrefix,
|
|
45985
|
+
isSkippedDueToActiveMigrationLock,
|
|
45986
|
+
};
|
|
45987
|
+
}
|
|
45953
45988
|
for (const prefix of selectedPrefixes) {
|
|
45954
45989
|
logger.info(`\n🏗️ Migrating prefix: "${prefix}"`);
|
|
45955
45990
|
const appliedCount = await migratePrefix({
|
|
@@ -45960,7 +45995,7 @@
|
|
|
45960
45995
|
logger,
|
|
45961
45996
|
migrationFiles,
|
|
45962
45997
|
migrationsDirectory,
|
|
45963
|
-
logSqlStatements: (
|
|
45998
|
+
logSqlStatements: (_e = options.logSqlStatements) !== null && _e !== void 0 ? _e : false,
|
|
45964
45999
|
});
|
|
45965
46000
|
perPrefix.push({ prefix, appliedCount });
|
|
45966
46001
|
}
|
|
@@ -45973,8 +46008,9 @@
|
|
|
45973
46008
|
}
|
|
45974
46009
|
return {
|
|
45975
46010
|
processedPrefixes: selectedPrefixes,
|
|
45976
|
-
totalMigrationFiles
|
|
46011
|
+
totalMigrationFiles,
|
|
45977
46012
|
perPrefix,
|
|
46013
|
+
isSkippedDueToActiveMigrationLock,
|
|
45978
46014
|
};
|
|
45979
46015
|
}
|
|
45980
46016
|
/**
|
|
@@ -48162,24 +48198,26 @@
|
|
|
48162
48198
|
*/
|
|
48163
48199
|
const MAX_PENDING_FILE_NAMES = 8;
|
|
48164
48200
|
/**
|
|
48165
|
-
*
|
|
48201
|
+
* Default verification options parsed from the current process arguments.
|
|
48166
48202
|
*/
|
|
48167
|
-
const
|
|
48203
|
+
const DEFAULT_VERIFY_PROMPTS_OPTIONS = normalizeVerifyPromptsOptions(parseVerifyPromptsCliOptions(process.argv.slice(2)));
|
|
48168
48204
|
/**
|
|
48169
48205
|
* Starts the verification loop and exits when no `[ ]` prompts remain.
|
|
48170
48206
|
*
|
|
48171
|
-
* @param reverse - Process files in reverse order
|
|
48172
|
-
*
|
|
48173
48207
|
* @public exported from `@promptbook/cli`
|
|
48174
48208
|
*/
|
|
48175
|
-
async function verifyPrompts(
|
|
48209
|
+
async function verifyPrompts(options = DEFAULT_VERIFY_PROMPTS_OPTIONS) {
|
|
48210
|
+
const normalizedOptions = normalizeVerifyPromptsOptions(options);
|
|
48176
48211
|
console.info(colors__default["default"].cyan.bold('📋 Prompt verification helper'));
|
|
48177
|
-
if (reverse) {
|
|
48212
|
+
if (normalizedOptions.reverse) {
|
|
48178
48213
|
console.info(colors__default["default"].gray('Processing files in reverse order'));
|
|
48179
48214
|
}
|
|
48180
|
-
|
|
48181
|
-
|
|
48182
|
-
|
|
48215
|
+
if (normalizedOptions.ignore.length > 0) {
|
|
48216
|
+
console.info(colors__default["default"].gray(`Ignoring candidates matching: ${normalizedOptions.ignore.join(', ')}`));
|
|
48217
|
+
}
|
|
48218
|
+
const { promptFiles: initialFiles, ignoredPromptFiles } = await loadPromptFilesForVerification(normalizedOptions);
|
|
48219
|
+
if (ignoredPromptFiles.length > 0) {
|
|
48220
|
+
console.info(colors__default["default"].gray(`Ignored ${ignoredPromptFiles.length} prompt file(s) for this run.`));
|
|
48183
48221
|
}
|
|
48184
48222
|
displayTopLevelFileList(initialFiles);
|
|
48185
48223
|
await prepareArchiveDirectory();
|
|
@@ -48194,10 +48232,7 @@
|
|
|
48194
48232
|
if (wasSkipped) {
|
|
48195
48233
|
skippedFiles.add(fileWithAllDone.path);
|
|
48196
48234
|
}
|
|
48197
|
-
promptFiles = await
|
|
48198
|
-
if (REVERSE_ORDER) {
|
|
48199
|
-
promptFiles.reverse();
|
|
48200
|
-
}
|
|
48235
|
+
promptFiles = (await loadPromptFilesForVerification(normalizedOptions)).promptFiles;
|
|
48201
48236
|
continue;
|
|
48202
48237
|
}
|
|
48203
48238
|
// Second priority: process todo prompts
|
|
@@ -48207,11 +48242,56 @@
|
|
|
48207
48242
|
break;
|
|
48208
48243
|
}
|
|
48209
48244
|
await resolvePrompt(nextPrompt);
|
|
48210
|
-
promptFiles = await
|
|
48211
|
-
|
|
48212
|
-
|
|
48245
|
+
promptFiles = (await loadPromptFilesForVerification(normalizedOptions)).promptFiles;
|
|
48246
|
+
}
|
|
48247
|
+
}
|
|
48248
|
+
/**
|
|
48249
|
+
* Parses supported command-line arguments for the standalone verification script.
|
|
48250
|
+
*/
|
|
48251
|
+
function parseVerifyPromptsCliOptions(args) {
|
|
48252
|
+
return {
|
|
48253
|
+
reverse: args.includes('--reverse'),
|
|
48254
|
+
ignore: readRepeatableStringOption(args, '--ignore'),
|
|
48255
|
+
};
|
|
48256
|
+
}
|
|
48257
|
+
/**
|
|
48258
|
+
* Loads prompt files and applies ordering plus ignore filters for one verification pass.
|
|
48259
|
+
*/
|
|
48260
|
+
async function loadPromptFilesForVerification(options) {
|
|
48261
|
+
const loadedPromptFiles = await loadPromptFiles(PROMPTS_DIR);
|
|
48262
|
+
const { promptFiles, ignoredPromptFiles } = partitionPromptFilesByIgnore(loadedPromptFiles, options.ignore);
|
|
48263
|
+
if (options.reverse) {
|
|
48264
|
+
promptFiles.reverse();
|
|
48265
|
+
}
|
|
48266
|
+
return { promptFiles, ignoredPromptFiles };
|
|
48267
|
+
}
|
|
48268
|
+
/**
|
|
48269
|
+
* Splits prompt files into files that should be verified now and files ignored for this run.
|
|
48270
|
+
*
|
|
48271
|
+
* @public exported from `@promptbook/cli`
|
|
48272
|
+
*/
|
|
48273
|
+
function partitionPromptFilesByIgnore(promptFiles, ignoreValues) {
|
|
48274
|
+
const normalizedIgnoreValues = normalizeIgnoreValues(ignoreValues);
|
|
48275
|
+
if (normalizedIgnoreValues.length === 0) {
|
|
48276
|
+
return {
|
|
48277
|
+
promptFiles: [...promptFiles],
|
|
48278
|
+
ignoredPromptFiles: [],
|
|
48279
|
+
};
|
|
48280
|
+
}
|
|
48281
|
+
const promptFilesToVerify = [];
|
|
48282
|
+
const ignoredPromptFiles = [];
|
|
48283
|
+
for (const promptFile of promptFiles) {
|
|
48284
|
+
if (matchesIgnoredPromptFile(promptFile, normalizedIgnoreValues)) {
|
|
48285
|
+
ignoredPromptFiles.push(promptFile);
|
|
48286
|
+
}
|
|
48287
|
+
else {
|
|
48288
|
+
promptFilesToVerify.push(promptFile);
|
|
48213
48289
|
}
|
|
48214
48290
|
}
|
|
48291
|
+
return {
|
|
48292
|
+
promptFiles: promptFilesToVerify,
|
|
48293
|
+
ignoredPromptFiles,
|
|
48294
|
+
};
|
|
48215
48295
|
}
|
|
48216
48296
|
/**
|
|
48217
48297
|
* Ensures the destination directory for completed prompts exists.
|
|
@@ -48219,13 +48299,92 @@
|
|
|
48219
48299
|
async function prepareArchiveDirectory() {
|
|
48220
48300
|
await promises.mkdir(DONE_PROMPTS_DIR, { recursive: true });
|
|
48221
48301
|
}
|
|
48302
|
+
/**
|
|
48303
|
+
* Normalizes verification options so the rest of the flow can assume stable defaults.
|
|
48304
|
+
*/
|
|
48305
|
+
function normalizeVerifyPromptsOptions(options) {
|
|
48306
|
+
var _a, _b;
|
|
48307
|
+
return {
|
|
48308
|
+
reverse: (_a = options.reverse) !== null && _a !== void 0 ? _a : false,
|
|
48309
|
+
ignore: normalizeIgnoreValues((_b = options.ignore) !== null && _b !== void 0 ? _b : []),
|
|
48310
|
+
};
|
|
48311
|
+
}
|
|
48312
|
+
/**
|
|
48313
|
+
* Normalizes ignore values and removes empty or duplicate entries case-insensitively.
|
|
48314
|
+
*/
|
|
48315
|
+
function normalizeIgnoreValues(ignoreValues) {
|
|
48316
|
+
const normalizedIgnoreValues = [];
|
|
48317
|
+
const seenIgnoreValues = new Set();
|
|
48318
|
+
for (const ignoreValue of ignoreValues) {
|
|
48319
|
+
const trimmedIgnoreValue = ignoreValue.trim();
|
|
48320
|
+
if (!trimmedIgnoreValue) {
|
|
48321
|
+
continue;
|
|
48322
|
+
}
|
|
48323
|
+
const lowerCasedIgnoreValue = trimmedIgnoreValue.toLowerCase();
|
|
48324
|
+
if (seenIgnoreValues.has(lowerCasedIgnoreValue)) {
|
|
48325
|
+
continue;
|
|
48326
|
+
}
|
|
48327
|
+
seenIgnoreValues.add(lowerCasedIgnoreValue);
|
|
48328
|
+
normalizedIgnoreValues.push(trimmedIgnoreValue);
|
|
48329
|
+
}
|
|
48330
|
+
return normalizedIgnoreValues;
|
|
48331
|
+
}
|
|
48332
|
+
/**
|
|
48333
|
+
* Reads one repeatable string option from raw CLI arguments.
|
|
48334
|
+
*/
|
|
48335
|
+
function readRepeatableStringOption(args, flag) {
|
|
48336
|
+
const values = [];
|
|
48337
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
48338
|
+
const argument = args[index];
|
|
48339
|
+
if (!argument) {
|
|
48340
|
+
continue;
|
|
48341
|
+
}
|
|
48342
|
+
if (argument === flag) {
|
|
48343
|
+
const nextValue = args[index + 1];
|
|
48344
|
+
if (nextValue !== undefined && !nextValue.startsWith('--')) {
|
|
48345
|
+
values.push(nextValue);
|
|
48346
|
+
index += 1;
|
|
48347
|
+
}
|
|
48348
|
+
continue;
|
|
48349
|
+
}
|
|
48350
|
+
if (argument.startsWith(`${flag}=`)) {
|
|
48351
|
+
values.push(argument.slice(flag.length + 1));
|
|
48352
|
+
}
|
|
48353
|
+
}
|
|
48354
|
+
return values;
|
|
48355
|
+
}
|
|
48356
|
+
/**
|
|
48357
|
+
* Resolves whether a prompt file should be ignored for this verification run.
|
|
48358
|
+
*/
|
|
48359
|
+
function matchesIgnoredPromptFile(promptFile, ignoreValues) {
|
|
48360
|
+
const searchableValues = [promptFile.name, getPromptFileFirstLine(promptFile)].map((value) => value.toLowerCase());
|
|
48361
|
+
return ignoreValues.some((ignoreValue) => {
|
|
48362
|
+
const lowerCasedIgnoreValue = ignoreValue.toLowerCase();
|
|
48363
|
+
return searchableValues.some((searchableValue) => searchableValue.includes(lowerCasedIgnoreValue));
|
|
48364
|
+
});
|
|
48365
|
+
}
|
|
48366
|
+
/**
|
|
48367
|
+
* Returns the first meaningful line of the prompt file after the status line.
|
|
48368
|
+
*/
|
|
48369
|
+
function getPromptFileFirstLine(promptFile) {
|
|
48370
|
+
var _a;
|
|
48371
|
+
const firstSection = promptFile.sections[0];
|
|
48372
|
+
const startLineIndex = (firstSection === null || firstSection === void 0 ? void 0 : firstSection.statusLineIndex) !== undefined ? firstSection.statusLineIndex + 1 : ((_a = firstSection === null || firstSection === void 0 ? void 0 : firstSection.startLine) !== null && _a !== void 0 ? _a : 0);
|
|
48373
|
+
for (let index = startLineIndex; index < promptFile.lines.length; index += 1) {
|
|
48374
|
+
const line = promptFile.lines[index];
|
|
48375
|
+
if (line !== undefined && line.trim() !== '') {
|
|
48376
|
+
return line.trim();
|
|
48377
|
+
}
|
|
48378
|
+
}
|
|
48379
|
+
return '';
|
|
48380
|
+
}
|
|
48222
48381
|
/**
|
|
48223
48382
|
* Displays the list of files that currently live in the prompts root.
|
|
48224
48383
|
*/
|
|
48225
48384
|
function displayTopLevelFileList(promptFiles) {
|
|
48226
48385
|
console.info(colors__default["default"].cyan('\nTop-level prompt files:'));
|
|
48227
48386
|
if (!promptFiles.length) {
|
|
48228
|
-
console.info(colors__default["default"].gray(' (no markdown files found in prompts/)'));
|
|
48387
|
+
console.info(colors__default["default"].gray(' (no prompt markdown files found for this run in prompts/)'));
|
|
48229
48388
|
return;
|
|
48230
48389
|
}
|
|
48231
48390
|
for (const file of promptFiles) {
|
|
@@ -48542,7 +48701,7 @@
|
|
|
48542
48701
|
}
|
|
48543
48702
|
// Note: When run as a standalone script, call the exported function
|
|
48544
48703
|
if (require.main === module) {
|
|
48545
|
-
verifyPrompts(
|
|
48704
|
+
verifyPrompts(DEFAULT_VERIFY_PROMPTS_OPTIONS).catch((error) => {
|
|
48546
48705
|
console.error(colors__default["default"].bgRed('Prompt verification failed:'), error);
|
|
48547
48706
|
process.exit(1);
|
|
48548
48707
|
});
|
|
@@ -48550,7 +48709,8 @@
|
|
|
48550
48709
|
|
|
48551
48710
|
var verifyPrompts$1 = /*#__PURE__*/Object.freeze({
|
|
48552
48711
|
__proto__: null,
|
|
48553
|
-
verifyPrompts: verifyPrompts
|
|
48712
|
+
verifyPrompts: verifyPrompts,
|
|
48713
|
+
partitionPromptFilesByIgnore: partitionPromptFilesByIgnore
|
|
48554
48714
|
});
|
|
48555
48715
|
|
|
48556
48716
|
/**
|