@promptbook/cli 0.114.0-10 → 0.114.0-12
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/apps/agents-server/src/app/admin/messages/MessagesClient.tsx +8 -1
- package/apps/agents-server/src/app/admin/messages/send-email/SendEmailClient.tsx +193 -63
- package/apps/agents-server/src/app/admin/messages/send-email/actions.ts +25 -28
- package/apps/agents-server/src/app/admin/messages/send-email/emailTesting.ts +153 -0
- package/apps/agents-server/src/app/admin/messages/send-email/emailTestingAccess.ts +30 -0
- package/apps/agents-server/src/app/admin/messages/send-email/page.tsx +18 -5
- package/apps/agents-server/src/app/api/internal/agent-goal-chat-planned-messages/route.ts +34 -7
- package/apps/agents-server/src/message-providers/email/stalwart/StalwartMessageProvider.ts +2 -1
- package/apps/agents-server/src/utils/email/agentEmailAddress.ts +14 -0
- package/apps/agents-server/src/utils/email/sendEmailThroughStalwart.ts +2 -1
- package/esm/index.es.js +404 -115
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/runGoScript/$spawnLoggedBashScript.d.ts +25 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/$terminateLoggedBashProcessTree.d.ts +11 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +4 -0
- package/esm/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +5 -0
- package/esm/src/book-2.0/agent-source/ParsedUnknownCommitment.d.ts +26 -0
- package/esm/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.unknown.test.d.ts +1 -0
- package/esm/src/book-2.0/agent-source/getBookCommitmentLineType.d.ts +19 -0
- package/esm/src/book-2.0/agent-source/parseAgentSourceWithCommitments.unknown.test.d.ts +1 -0
- package/esm/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.d.ts +28 -0
- package/esm/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/harness/$checkHarnessInstallation.d.ts +3 -3
- package/esm/src/cli/cli-commands/common/harness/$checkHarnessInstallation.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -3
- package/esm/src/cli/cli-commands/common/harness/HarnessInstallationStatus.d.ts +3 -2
- package/esm/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +29 -0
- package/esm/src/cli/cli-commands/common/harnessUpdateCliOptions.test.d.ts +1 -0
- package/esm/src/executables/platforms/locateAppOnWindows.d.ts +1 -1
- package/esm/src/executables/platforms/locateAppOnWindows.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/book-2.0/agent-source/AgentSourceParseResult.ts +6 -0
- package/src/book-2.0/agent-source/ParsedUnknownCommitment.ts +29 -0
- package/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments/augmentAgentModelRequirementsFromSource.ts +38 -1
- package/src/book-2.0/agent-source/getBookCommitmentLineType.ts +36 -0
- package/src/book-2.0/agent-source/parseAgentSourceWithCommitments.ts +128 -61
- package/src/book-components/BookEditor/BookEditorMonaco.tsx +6 -1
- package/src/book-components/BookEditor/BookEditorMonacoTokenization.ts +3 -1
- package/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.ts +50 -0
- package/src/cli/cli-commands/coder/boilerplateTemplates.ts +3 -15
- package/src/cli/cli-commands/coder/init.ts +11 -2
- package/src/cli/cli-commands/coder/ping.ts +11 -1
- package/src/cli/cli-commands/coder/run.ts +11 -2
- package/src/cli/cli-commands/coder/server.ts +11 -2
- package/src/cli/cli-commands/common/harness/$applyHarnessInstallationStatus.ts +5 -0
- package/src/cli/cli-commands/common/harness/$checkHarnessInstallation.ts +17 -5
- package/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.ts +6 -3
- package/src/cli/cli-commands/common/harness/HarnessInstallationStatus.ts +3 -2
- package/src/cli/cli-commands/common/harnessUpdateCliOptions.ts +49 -0
- package/src/executables/platforms/locateAppOnWindows.ts +12 -9
- package/src/other/templates/getTemplatesPipelineCollection.ts +881 -685
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +403 -114
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/runGoScript/$spawnLoggedBashScript.d.ts +25 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/$terminateLoggedBashProcessTree.d.ts +11 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +4 -0
- package/umd/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +5 -0
- package/umd/src/book-2.0/agent-source/ParsedUnknownCommitment.d.ts +26 -0
- package/umd/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.unknown.test.d.ts +1 -0
- package/umd/src/book-2.0/agent-source/getBookCommitmentLineType.d.ts +19 -0
- package/umd/src/book-2.0/agent-source/parseAgentSourceWithCommitments.unknown.test.d.ts +1 -0
- package/umd/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.d.ts +28 -0
- package/umd/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/harness/$checkHarnessInstallation.d.ts +3 -3
- package/umd/src/cli/cli-commands/common/harness/$checkHarnessInstallation.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -3
- package/umd/src/cli/cli-commands/common/harness/HarnessInstallationStatus.d.ts +3 -2
- package/umd/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +29 -0
- package/umd/src/cli/cli-commands/common/harnessUpdateCliOptions.test.d.ts +1 -0
- package/umd/src/executables/platforms/locateAppOnWindows.d.ts +1 -1
- package/umd/src/executables/platforms/locateAppOnWindows.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -4,7 +4,7 @@ import _spaceTrim, { spaceTrim as spaceTrim$1 } from 'spacetrim';
|
|
|
4
4
|
import { writeFile, stat, mkdir, readFile, readdir, rm, cp, lstat, symlink, rename, unlink, appendFile, realpath, copyFile, access, constants, watch, rmdir } from 'fs/promises';
|
|
5
5
|
import { join, delimiter, relative, basename, resolve, dirname, isAbsolute, extname } from 'path';
|
|
6
6
|
import { createHash, randomBytes } from 'crypto';
|
|
7
|
-
import { spawn } from 'child_process';
|
|
7
|
+
import { spawn, spawnSync } from 'child_process';
|
|
8
8
|
import moment from 'moment';
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import { createWriteStream, mkdirSync, writeFileSync, statSync, readFileSync, existsSync, promises } from 'fs';
|
|
@@ -48,7 +48,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
48
48
|
* @generated
|
|
49
49
|
* @see https://github.com/webgptorg/promptbook
|
|
50
50
|
*/
|
|
51
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-
|
|
51
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-12';
|
|
52
52
|
/**
|
|
53
53
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
54
54
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -20307,6 +20307,30 @@ const COMMITMENT_REGISTRY = [
|
|
|
20307
20307
|
// TODO: [🧠] Maybe create through standardized $register
|
|
20308
20308
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
20309
20309
|
|
|
20310
|
+
/**
|
|
20311
|
+
* Pattern shared by Book parsing and editor highlighting for a commitment-like line.
|
|
20312
|
+
*
|
|
20313
|
+
* A Book commitment keyword consists of one or more all-uppercase words with at least
|
|
20314
|
+
* two characters each. This deliberately mirrors the Book editor syntax rule so an
|
|
20315
|
+
* unknown keyword starts a new source block everywhere it is interpreted.
|
|
20316
|
+
*
|
|
20317
|
+
* @private internal constant of `getBookCommitmentLineType`
|
|
20318
|
+
*/
|
|
20319
|
+
const BOOK_COMMITMENT_LINE_TYPE_REGEX = /^\s*(?<type>[A-Z][A-Z0-9]+(?:\s+[A-Z][A-Z0-9]+)*)(?=\s|$)/;
|
|
20320
|
+
/**
|
|
20321
|
+
* Extracts the uppercase commitment type from a Book line, including types not registered by Promptbook.
|
|
20322
|
+
*
|
|
20323
|
+
* @param line - One raw Book source line.
|
|
20324
|
+
* @returns Matched commitment type or `null` when the line does not begin with commitment syntax.
|
|
20325
|
+
*
|
|
20326
|
+
* @private internal utility of Book parsing and `<BookEditor/>`
|
|
20327
|
+
*/
|
|
20328
|
+
function getBookCommitmentLineType(line) {
|
|
20329
|
+
var _a;
|
|
20330
|
+
const match = BOOK_COMMITMENT_LINE_TYPE_REGEX.exec(line);
|
|
20331
|
+
return ((_a = match === null || match === void 0 ? void 0 : match.groups) === null || _a === void 0 ? void 0 : _a.type) || null;
|
|
20332
|
+
}
|
|
20333
|
+
|
|
20310
20334
|
/**
|
|
20311
20335
|
* Consumes the agent-name prelude from raw source.
|
|
20312
20336
|
*
|
|
@@ -20364,13 +20388,15 @@ function parseAgentSourceWithCommitments(agentSource) {
|
|
|
20364
20388
|
return {
|
|
20365
20389
|
agentName: null,
|
|
20366
20390
|
commitments: [],
|
|
20391
|
+
unknownCommitments: [],
|
|
20367
20392
|
nonCommitmentLines: [],
|
|
20368
20393
|
};
|
|
20369
20394
|
}
|
|
20370
20395
|
const { lines, agentName, agentNameLineIndex, agentNameLineNumber } = parseAgentSourcePrelude(agentSource);
|
|
20371
20396
|
const commitments = [];
|
|
20397
|
+
const unknownCommitments = [];
|
|
20372
20398
|
const nonCommitmentLines = agentNameLineIndex >= 0 ? [lines[agentNameLineIndex]] : [];
|
|
20373
|
-
// Parse commitments with multiline support
|
|
20399
|
+
// Parse commitments with multiline support.
|
|
20374
20400
|
let currentCommitment = null;
|
|
20375
20401
|
// Process lines starting from after the agent name line
|
|
20376
20402
|
const startIndex = agentNameLineIndex >= 0 ? agentNameLineIndex + 1 : 0;
|
|
@@ -20384,25 +20410,11 @@ function parseAgentSourceWithCommitments(agentSource) {
|
|
|
20384
20410
|
// Check if this line starts or ends a code block
|
|
20385
20411
|
if (trimmedLine.startsWith('```')) {
|
|
20386
20412
|
isInsideCodeBlock = !isInsideCodeBlock;
|
|
20387
|
-
|
|
20388
|
-
// If we are inside a commitment, the code block is part of it
|
|
20389
|
-
currentCommitment.contentLines.push(line);
|
|
20390
|
-
}
|
|
20391
|
-
else {
|
|
20392
|
-
// If we are not inside a commitment, the code block is non-commitment
|
|
20393
|
-
nonCommitmentLines.push(line);
|
|
20394
|
-
}
|
|
20413
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
20395
20414
|
continue;
|
|
20396
20415
|
}
|
|
20397
20416
|
if (isInsideCodeBlock) {
|
|
20398
|
-
|
|
20399
|
-
// If we are inside a commitment and a code block, the line is part of the commitment
|
|
20400
|
-
currentCommitment.contentLines.push(line);
|
|
20401
|
-
}
|
|
20402
|
-
else {
|
|
20403
|
-
// If we are inside a code block but not a commitment, the line is non-commitment
|
|
20404
|
-
nonCommitmentLines.push(line);
|
|
20405
|
-
}
|
|
20417
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
20406
20418
|
continue;
|
|
20407
20419
|
}
|
|
20408
20420
|
// Check if this line starts a new commitment
|
|
@@ -20411,22 +20423,14 @@ function parseAgentSourceWithCommitments(agentSource) {
|
|
|
20411
20423
|
const typeRegex = definition.createTypeRegex();
|
|
20412
20424
|
const match = typeRegex.exec(line.trim());
|
|
20413
20425
|
if (match && ((_a = match.groups) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
20414
|
-
|
|
20415
|
-
if (currentCommitment) {
|
|
20416
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
20417
|
-
commitments.push({
|
|
20418
|
-
type: currentCommitment.type,
|
|
20419
|
-
content: spaceTrim$1(fullContent),
|
|
20420
|
-
originalLine: currentCommitment.originalStartLine,
|
|
20421
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
20422
|
-
});
|
|
20423
|
-
}
|
|
20426
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20424
20427
|
// Extract the initial content from the commitment line
|
|
20425
20428
|
const fullRegex = definition.createRegex();
|
|
20426
20429
|
const fullMatch = fullRegex.exec(line.trim());
|
|
20427
20430
|
const initialContent = ((_b = fullMatch === null || fullMatch === void 0 ? void 0 : fullMatch.groups) === null || _b === void 0 ? void 0 : _b.contents) || '';
|
|
20428
20431
|
// Start a new commitment
|
|
20429
20432
|
currentCommitment = {
|
|
20433
|
+
kind: 'known',
|
|
20430
20434
|
type: definition.type,
|
|
20431
20435
|
startLineNumber: i + 1,
|
|
20432
20436
|
originalStartLine: line,
|
|
@@ -20436,52 +20440,90 @@ function parseAgentSourceWithCommitments(agentSource) {
|
|
|
20436
20440
|
break;
|
|
20437
20441
|
}
|
|
20438
20442
|
}
|
|
20443
|
+
if (foundNewCommitment) {
|
|
20444
|
+
continue;
|
|
20445
|
+
}
|
|
20446
|
+
const unknownCommitmentType = getBookCommitmentLineType(line);
|
|
20447
|
+
if (unknownCommitmentType) {
|
|
20448
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20449
|
+
currentCommitment = {
|
|
20450
|
+
kind: 'unknown',
|
|
20451
|
+
type: unknownCommitmentType,
|
|
20452
|
+
startLineNumber: i + 1,
|
|
20453
|
+
originalStartLine: line,
|
|
20454
|
+
sourceLines: [line],
|
|
20455
|
+
};
|
|
20456
|
+
continue;
|
|
20457
|
+
}
|
|
20439
20458
|
// Check if this is a horizontal line (ends any current commitment)
|
|
20440
20459
|
const isHorizontalLine = HORIZONTAL_LINE_PATTERN$1.test(line);
|
|
20441
20460
|
if (isHorizontalLine) {
|
|
20442
|
-
|
|
20443
|
-
|
|
20444
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
20445
|
-
commitments.push({
|
|
20446
|
-
type: currentCommitment.type,
|
|
20447
|
-
content: spaceTrim$1(fullContent),
|
|
20448
|
-
originalLine: currentCommitment.originalStartLine,
|
|
20449
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
20450
|
-
});
|
|
20451
|
-
currentCommitment = null;
|
|
20452
|
-
}
|
|
20461
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20462
|
+
currentCommitment = null;
|
|
20453
20463
|
// Add horizontal line to non-commitment lines
|
|
20454
20464
|
nonCommitmentLines.push(line);
|
|
20455
20465
|
continue;
|
|
20456
20466
|
}
|
|
20457
|
-
|
|
20458
|
-
if (currentCommitment) {
|
|
20459
|
-
// This line belongs to the current commitment
|
|
20460
|
-
currentCommitment.contentLines.push(line);
|
|
20461
|
-
}
|
|
20462
|
-
else {
|
|
20463
|
-
// This line is not part of any commitment
|
|
20464
|
-
nonCommitmentLines.push(line);
|
|
20465
|
-
}
|
|
20466
|
-
}
|
|
20467
|
-
}
|
|
20468
|
-
// Don't forget to save the last commitment if it exists
|
|
20469
|
-
if (currentCommitment) {
|
|
20470
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
20471
|
-
commitments.push({
|
|
20472
|
-
type: currentCommitment.type,
|
|
20473
|
-
content: spaceTrim$1(fullContent),
|
|
20474
|
-
originalLine: currentCommitment.originalStartLine,
|
|
20475
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
20476
|
-
});
|
|
20467
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
20477
20468
|
}
|
|
20469
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20478
20470
|
return {
|
|
20479
20471
|
agentName,
|
|
20480
20472
|
agentNameLineNumber,
|
|
20481
20473
|
commitments,
|
|
20474
|
+
unknownCommitments,
|
|
20482
20475
|
nonCommitmentLines,
|
|
20483
20476
|
};
|
|
20484
20477
|
}
|
|
20478
|
+
/**
|
|
20479
|
+
* Stores the current known or unknown commitment in its appropriate parsed collection.
|
|
20480
|
+
*
|
|
20481
|
+
* @param currentCommitment - Commitment-like block collected so far.
|
|
20482
|
+
* @param commitments - Parsed registered commitments to append to.
|
|
20483
|
+
* @param unknownCommitments - Parsed unregistered commitments to append to.
|
|
20484
|
+
*
|
|
20485
|
+
* @private internal utility of `parseAgentSourceWithCommitments`
|
|
20486
|
+
*/
|
|
20487
|
+
function appendCurrentCommitment(currentCommitment, commitments, unknownCommitments) {
|
|
20488
|
+
if (!currentCommitment) {
|
|
20489
|
+
return;
|
|
20490
|
+
}
|
|
20491
|
+
if (currentCommitment.kind === 'unknown') {
|
|
20492
|
+
unknownCommitments.push({
|
|
20493
|
+
type: currentCommitment.type,
|
|
20494
|
+
originalLine: currentCommitment.originalStartLine,
|
|
20495
|
+
lineNumber: currentCommitment.startLineNumber,
|
|
20496
|
+
source: spaceTrim$1(currentCommitment.sourceLines.join('\n')),
|
|
20497
|
+
});
|
|
20498
|
+
return;
|
|
20499
|
+
}
|
|
20500
|
+
commitments.push({
|
|
20501
|
+
type: currentCommitment.type,
|
|
20502
|
+
content: spaceTrim$1(currentCommitment.contentLines.join('\n')),
|
|
20503
|
+
originalLine: currentCommitment.originalStartLine,
|
|
20504
|
+
lineNumber: currentCommitment.startLineNumber,
|
|
20505
|
+
});
|
|
20506
|
+
}
|
|
20507
|
+
/**
|
|
20508
|
+
* Adds one source line to the active commitment-like block, or to plain source content when none is active.
|
|
20509
|
+
*
|
|
20510
|
+
* @param currentCommitment - Commitment-like block currently being collected.
|
|
20511
|
+
* @param line - Source line to append.
|
|
20512
|
+
* @param nonCommitmentLines - Plain source lines to append to when no block is active.
|
|
20513
|
+
*
|
|
20514
|
+
* @private internal utility of `parseAgentSourceWithCommitments`
|
|
20515
|
+
*/
|
|
20516
|
+
function appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines) {
|
|
20517
|
+
if (!currentCommitment) {
|
|
20518
|
+
nonCommitmentLines.push(line);
|
|
20519
|
+
return;
|
|
20520
|
+
}
|
|
20521
|
+
if (currentCommitment.kind === 'unknown') {
|
|
20522
|
+
currentCommitment.sourceLines.push(line);
|
|
20523
|
+
return;
|
|
20524
|
+
}
|
|
20525
|
+
currentCommitment.contentLines.push(line);
|
|
20526
|
+
}
|
|
20485
20527
|
|
|
20486
20528
|
/**
|
|
20487
20529
|
* Parses parameters from text using both supported notations:
|
|
@@ -24751,14 +24793,90 @@ const PTBK_CODER_LOG_FILE_ENV_NAME = 'PTBK_CODER_LOG_FILE';
|
|
|
24751
24793
|
* without the generated script and the prompt it embeds.
|
|
24752
24794
|
*/
|
|
24753
24795
|
const SCRIPT_EXECUTION_LOG_RAW_OUTPUT_MARKER = '--- raw output ---';
|
|
24796
|
+
/**
|
|
24797
|
+
* Command which terminates the Bash process tree rooted at the running harness.
|
|
24798
|
+
*
|
|
24799
|
+
* Bash's POSIX process IDs differ from Windows process IDs in Git Bash, so the Windows branch resolves the native PID
|
|
24800
|
+
* before delegating to `taskkill`. Unix harnesses run in a dedicated Bash job process group, which can be terminated
|
|
24801
|
+
* with its negative process ID.
|
|
24802
|
+
*/
|
|
24803
|
+
const TERMINATE_BASH_PROCESS_TREE_COMMAND = process.platform === 'win32'
|
|
24804
|
+
? spaceTrim$1(`
|
|
24805
|
+
HARNESS_WINDOWS_PROCESS_ID="$(ps -l -p "$HARNESS_PROCESS_ID" | awk 'NR == 2 { print $4 }')"
|
|
24806
|
+
if [ -n "$HARNESS_WINDOWS_PROCESS_ID" ]; then
|
|
24807
|
+
MSYS_NO_PATHCONV=1 taskkill.exe /PID "$HARNESS_WINDOWS_PROCESS_ID" /T /F > /dev/null 2>&1 || true
|
|
24808
|
+
fi
|
|
24809
|
+
`)
|
|
24810
|
+
: 'kill -TERM -- "-$HARNESS_PROCESS_ID" 2>/dev/null || true';
|
|
24811
|
+
/**
|
|
24812
|
+
* Shell condition that detects whether the Node process which owns the harness is still running.
|
|
24813
|
+
*
|
|
24814
|
+
* Git Bash translates process IDs and command switches, so querying the native Windows PID needs both `tasklist` and
|
|
24815
|
+
* disabled MSYS path conversion there. Unix can use the native `kill -0` process existence check.
|
|
24816
|
+
*/
|
|
24817
|
+
const IS_PARENT_PROCESS_RUNNING_CONDITION = process.platform === 'win32'
|
|
24818
|
+
? 'MSYS_NO_PATHCONV=1 tasklist.exe /FI "PID eq $PARENT_CODER_PROCESS_ID" /NH | awk -v processId="$PARENT_CODER_PROCESS_ID" \'$2 == processId { isFound = 1 } END { exit isFound ? 0 : 1 }\''
|
|
24819
|
+
: 'kill -0 "$PARENT_CODER_PROCESS_ID" 2>/dev/null';
|
|
24820
|
+
/**
|
|
24821
|
+
* Environment variable that identifies the Node process responsible for a temporary harness shell.
|
|
24822
|
+
*/
|
|
24823
|
+
const PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME = 'PTBK_CODER_PARENT_PROCESS_ID';
|
|
24754
24824
|
/**
|
|
24755
24825
|
* Small bash wrapper that preserves stdout/stderr streams while teeing both into the runtime log file.
|
|
24826
|
+
*
|
|
24827
|
+
* A watcher polls the owning Node process by its PID. If that process exits abruptly, the watcher stops the whole
|
|
24828
|
+
* Bash and harness process tree instead of letting it continue as an orphan.
|
|
24756
24829
|
*/
|
|
24757
24830
|
const LOGGED_BASH_WRAPPER_COMMAND = spaceTrim$1(`
|
|
24831
|
+
PARENT_CODER_PROCESS_ID="\${${PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME}}"
|
|
24832
|
+
unset ${PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME}
|
|
24833
|
+
|
|
24834
|
+
terminate_harness_process_tree() {
|
|
24835
|
+
# Keep the EXIT cleanup intact so the wrapper can also stop its parent-process watcher.
|
|
24836
|
+
trap - HUP INT TERM
|
|
24837
|
+
${TERMINATE_BASH_PROCESS_TREE_COMMAND}
|
|
24838
|
+
}
|
|
24839
|
+
|
|
24840
|
+
is_parent_process_running() {
|
|
24841
|
+
${IS_PARENT_PROCESS_RUNNING_CONDITION}
|
|
24842
|
+
}
|
|
24843
|
+
|
|
24758
24844
|
if [ -n "\${${PTBK_CODER_LOG_FILE_ENV_NAME}:-}" ]; then
|
|
24759
|
-
exec > >(tee -a "
|
|
24845
|
+
exec > >(tee -a "$${PTBK_CODER_LOG_FILE_ENV_NAME}") 2> >(tee -a "$${PTBK_CODER_LOG_FILE_ENV_NAME}" >&2)
|
|
24846
|
+
fi
|
|
24847
|
+
|
|
24848
|
+
watch_parent_process() {
|
|
24849
|
+
trap 'exit 0' HUP INT TERM
|
|
24850
|
+
|
|
24851
|
+
while is_parent_process_running; do
|
|
24852
|
+
sleep 1
|
|
24853
|
+
done
|
|
24854
|
+
|
|
24855
|
+
terminate_harness_process_tree
|
|
24856
|
+
}
|
|
24857
|
+
|
|
24858
|
+
# Background harness jobs need their own process group on Unix so termination cannot reach the parent coder.
|
|
24859
|
+
set -m
|
|
24860
|
+
if ! is_parent_process_running; then
|
|
24861
|
+
exit 1
|
|
24760
24862
|
fi
|
|
24761
|
-
bash "$1"
|
|
24863
|
+
bash "$1" &
|
|
24864
|
+
HARNESS_PROCESS_ID=$!
|
|
24865
|
+
|
|
24866
|
+
cleanup_parent_process_watcher() {
|
|
24867
|
+
kill "$PARENT_PROCESS_WATCHER_PID" 2>/dev/null || true
|
|
24868
|
+
wait "$PARENT_PROCESS_WATCHER_PID" 2>/dev/null || true
|
|
24869
|
+
}
|
|
24870
|
+
|
|
24871
|
+
watch_parent_process &
|
|
24872
|
+
PARENT_PROCESS_WATCHER_PID=$!
|
|
24873
|
+
|
|
24874
|
+
trap cleanup_parent_process_watcher EXIT
|
|
24875
|
+
trap terminate_harness_process_tree HUP INT TERM
|
|
24876
|
+
|
|
24877
|
+
wait "$HARNESS_PROCESS_ID"
|
|
24878
|
+
SCRIPT_EXIT_CODE=$?
|
|
24879
|
+
exit "$SCRIPT_EXIT_CODE"
|
|
24762
24880
|
`);
|
|
24763
24881
|
/**
|
|
24764
24882
|
* Shapes one bash invocation that optionally mirrors live script output into a temporary log file.
|
|
@@ -24814,6 +24932,38 @@ function describeTempScriptKind(scriptPath) {
|
|
|
24814
24932
|
return scriptPath.toLowerCase().endsWith('.test.sh') ? 'test shell' : 'runner shell';
|
|
24815
24933
|
}
|
|
24816
24934
|
|
|
24935
|
+
/**
|
|
24936
|
+
* Standard streams used by every temporary Bash runner.
|
|
24937
|
+
*/
|
|
24938
|
+
const BASH_PROCESS_STDIO = ['pipe', 'pipe', 'pipe'];
|
|
24939
|
+
/**
|
|
24940
|
+
* Whether the current Node process is running on Windows.
|
|
24941
|
+
*/
|
|
24942
|
+
const IS_WINDOWS$1 = process.platform === 'win32';
|
|
24943
|
+
/**
|
|
24944
|
+
* Starts one temporary Bash script in a process tree owned by the current Node process.
|
|
24945
|
+
*
|
|
24946
|
+
* The wrapper watches the supplied owning process ID. When that process exits abruptly, the wrapper terminates every
|
|
24947
|
+
* nested shell and harness process instead of leaving it orphaned.
|
|
24948
|
+
*
|
|
24949
|
+
* @private internal utility of the coding prompt runner
|
|
24950
|
+
*/
|
|
24951
|
+
function $spawnLoggedBashScript(options) {
|
|
24952
|
+
var _a;
|
|
24953
|
+
const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
|
|
24954
|
+
const parentProcessId = (_a = options.parentProcessId) !== null && _a !== void 0 ? _a : process.pid;
|
|
24955
|
+
return spawn('bash', bashExecution.args, {
|
|
24956
|
+
detached: !IS_WINDOWS$1,
|
|
24957
|
+
env: {
|
|
24958
|
+
...process.env,
|
|
24959
|
+
...bashExecution.env,
|
|
24960
|
+
[PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME]: parentProcessId.toString(),
|
|
24961
|
+
},
|
|
24962
|
+
stdio: BASH_PROCESS_STDIO,
|
|
24963
|
+
windowsHide: true,
|
|
24964
|
+
});
|
|
24965
|
+
}
|
|
24966
|
+
|
|
24817
24967
|
/**
|
|
24818
24968
|
* Prints one live shell output chunk to the terminal when console mirroring is enabled.
|
|
24819
24969
|
*/
|
|
@@ -24836,12 +24986,12 @@ function printLiveScriptChunk(chunk, source, shouldPrintLiveOutput) {
|
|
|
24836
24986
|
async function runBashScriptWithOutput(options) {
|
|
24837
24987
|
var _a;
|
|
24838
24988
|
await appendScriptExecutionLogStart(options);
|
|
24839
|
-
const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
|
|
24840
24989
|
const scriptPathPosix = toPosixPath(options.scriptPath);
|
|
24841
24990
|
const shouldPrintLiveOutput = (_a = options.shouldPrintLiveOutput) !== null && _a !== void 0 ? _a : true;
|
|
24842
24991
|
return await new Promise((resolve, reject) => {
|
|
24843
|
-
const commandProcess =
|
|
24844
|
-
|
|
24992
|
+
const commandProcess = $spawnLoggedBashScript({
|
|
24993
|
+
scriptPath: options.scriptPath,
|
|
24994
|
+
logPath: options.logPath,
|
|
24845
24995
|
});
|
|
24846
24996
|
let output = '';
|
|
24847
24997
|
let settled = false;
|
|
@@ -24900,8 +25050,9 @@ async function runBashScriptWithOutput(options) {
|
|
|
24900
25050
|
const failure = new Error(spaceTrim$1(output) || `Command "bash ${scriptPathPosix}" exited with code ${code}`);
|
|
24901
25051
|
settleWithLog(`failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`, () => reject(failure), failure);
|
|
24902
25052
|
};
|
|
25053
|
+
// Wait for `close`, not only `exit`, because the Bash wrapper can still be flushing its tee process
|
|
25054
|
+
// substitutions after the direct shell exits.
|
|
24903
25055
|
commandProcess.on('close', handleExit);
|
|
24904
|
-
commandProcess.on('exit', handleExit);
|
|
24905
25056
|
commandProcess.on('disconnect', () => {
|
|
24906
25057
|
const failure = new Error(`Command "bash ${scriptPathPosix}" disconnected`);
|
|
24907
25058
|
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
@@ -25762,6 +25913,35 @@ function isGitHubCopilotArgumentLimitError(error) {
|
|
|
25762
25913
|
error.message.includes('bin/node'));
|
|
25763
25914
|
}
|
|
25764
25915
|
|
|
25916
|
+
/**
|
|
25917
|
+
* Whether the current coder process runs on Windows.
|
|
25918
|
+
*/
|
|
25919
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
25920
|
+
/**
|
|
25921
|
+
* Stops one active temporary Bash shell together with the harness process tree it owns.
|
|
25922
|
+
*
|
|
25923
|
+
* Unix sends `SIGTERM` to the wrapper so its shell trap terminates the separately grouped harness job. Windows does
|
|
25924
|
+
* not reliably deliver that signal to Bash, so the native `taskkill` command terminates the direct shell tree instead.
|
|
25925
|
+
*
|
|
25926
|
+
* @private internal utility of the coding prompt runner
|
|
25927
|
+
*/
|
|
25928
|
+
function $terminateLoggedBashProcessTree(commandProcess) {
|
|
25929
|
+
if (commandProcess.exitCode !== null || commandProcess.signalCode !== null) {
|
|
25930
|
+
return;
|
|
25931
|
+
}
|
|
25932
|
+
if (!IS_WINDOWS) {
|
|
25933
|
+
commandProcess.kill('SIGTERM');
|
|
25934
|
+
return;
|
|
25935
|
+
}
|
|
25936
|
+
if (!commandProcess.pid) {
|
|
25937
|
+
return;
|
|
25938
|
+
}
|
|
25939
|
+
spawnSync('taskkill.exe', ['/PID', commandProcess.pid.toString(), '/T', '/F'], {
|
|
25940
|
+
stdio: 'ignore',
|
|
25941
|
+
windowsHide: true,
|
|
25942
|
+
});
|
|
25943
|
+
}
|
|
25944
|
+
|
|
25765
25945
|
/**
|
|
25766
25946
|
* Maximum number of output characters included in thrown error messages.
|
|
25767
25947
|
*/
|
|
@@ -25804,15 +25984,16 @@ async function runScriptUntilMarkerIdle(options) {
|
|
|
25804
25984
|
const scriptPathPosix = toPosixPath(scriptPath);
|
|
25805
25985
|
const shouldPrintLiveOutput = (_a = options.shouldPrintLiveOutput) !== null && _a !== void 0 ? _a : true;
|
|
25806
25986
|
await appendScriptExecutionLogStart(options);
|
|
25807
|
-
const bashExecution = buildLoggedBashExecution(scriptPath, options.logPath);
|
|
25808
25987
|
return await new Promise((resolve, reject) => {
|
|
25809
|
-
const commandProcess =
|
|
25810
|
-
|
|
25988
|
+
const commandProcess = $spawnLoggedBashScript({
|
|
25989
|
+
scriptPath,
|
|
25990
|
+
logPath: options.logPath,
|
|
25811
25991
|
});
|
|
25812
25992
|
let stdoutBuffer = '';
|
|
25813
25993
|
let stderrBuffer = '';
|
|
25814
25994
|
let fullOutput = '';
|
|
25815
25995
|
let markerSeen = false;
|
|
25996
|
+
let isCompletedAfterIdleTimeout = false;
|
|
25816
25997
|
let idleTimer;
|
|
25817
25998
|
let settled = false;
|
|
25818
25999
|
let isSettling = false;
|
|
@@ -25854,15 +26035,16 @@ async function runScriptUntilMarkerIdle(options) {
|
|
|
25854
26035
|
});
|
|
25855
26036
|
};
|
|
25856
26037
|
/**
|
|
25857
|
-
*
|
|
26038
|
+
* Stops a marker-completed process tree after its trailing output becomes idle.
|
|
25858
26039
|
*/
|
|
25859
26040
|
const finishAfterIdleTimeout = () => {
|
|
25860
|
-
|
|
26041
|
+
isCompletedAfterIdleTimeout = true;
|
|
26042
|
+
idleTimer = undefined;
|
|
25861
26043
|
try {
|
|
25862
|
-
commandProcess
|
|
26044
|
+
$terminateLoggedBashProcessTree(commandProcess);
|
|
25863
26045
|
}
|
|
25864
26046
|
catch (_a) {
|
|
25865
|
-
//
|
|
26047
|
+
// The close handler below still settles normally when Bash already exited before the idle timer fired.
|
|
25866
26048
|
}
|
|
25867
26049
|
};
|
|
25868
26050
|
/**
|
|
@@ -25921,7 +26103,11 @@ async function runScriptUntilMarkerIdle(options) {
|
|
|
25921
26103
|
const failure = code === 0 || markerSeen
|
|
25922
26104
|
? undefined
|
|
25923
26105
|
: new Error(buildCommandFailureMessage(scriptPathPosix, code, fullOutput));
|
|
25924
|
-
const status =
|
|
26106
|
+
const status = isCompletedAfterIdleTimeout
|
|
26107
|
+
? 'completed after idle timeout'
|
|
26108
|
+
: failure
|
|
26109
|
+
? `failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`
|
|
26110
|
+
: 'succeeded';
|
|
25925
26111
|
settleWithLog(status, () => {
|
|
25926
26112
|
if (!failure) {
|
|
25927
26113
|
resolve(fullOutput);
|
|
@@ -25930,8 +26116,9 @@ async function runScriptUntilMarkerIdle(options) {
|
|
|
25930
26116
|
reject(failure);
|
|
25931
26117
|
});
|
|
25932
26118
|
};
|
|
26119
|
+
// Wait for `close`, not only `exit`, because the Bash wrapper can still be flushing its tee process
|
|
26120
|
+
// substitutions after the direct shell exits.
|
|
25933
26121
|
commandProcess.on('close', handleExit);
|
|
25934
|
-
commandProcess.on('exit', handleExit);
|
|
25935
26122
|
commandProcess.on('disconnect', () => {
|
|
25936
26123
|
const failure = new Error(buildCommandFailureMessage(scriptPathPosix, null, fullOutput));
|
|
25937
26124
|
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
@@ -36801,7 +36988,8 @@ async function augmentAgentModelRequirementsFromSource(requirements, parseResult
|
|
|
36801
36988
|
requirements = await importReferencedFiles(requirements);
|
|
36802
36989
|
requirements = appendMcpServers(requirements, agentSource);
|
|
36803
36990
|
requirements = appendNonCommitmentContent(requirements, parseResult);
|
|
36804
|
-
|
|
36991
|
+
requirements = appendExampleInteractions(requirements, parseResult);
|
|
36992
|
+
return appendUnknownCommitmentContent(requirements, parseResult);
|
|
36805
36993
|
}
|
|
36806
36994
|
/**
|
|
36807
36995
|
* Imports text files referenced by IMPORT commitments and appends their transformed content to the system message.
|
|
@@ -36923,6 +37111,36 @@ function appendNonCommitmentContent(requirements, parseResult) {
|
|
|
36923
37111
|
}
|
|
36924
37112
|
return appendSystemMessageSection(requirements, nonCommitmentContent);
|
|
36925
37113
|
}
|
|
37114
|
+
/**
|
|
37115
|
+
* Appends unknown commitment blocks as final extra context without applying commitment side effects.
|
|
37116
|
+
*
|
|
37117
|
+
* @param requirements - Current requirements snapshot.
|
|
37118
|
+
* @param parseResult - Parsed source including unknown commitment blocks.
|
|
37119
|
+
* @returns Requirements with unknown commitment context appended at the end of the system message.
|
|
37120
|
+
*
|
|
37121
|
+
* @private internal utility of `augmentAgentModelRequirementsFromSource`
|
|
37122
|
+
*/
|
|
37123
|
+
function appendUnknownCommitmentContent(requirements, parseResult) {
|
|
37124
|
+
const unknownCommitmentContent = getUnknownCommitmentContent(parseResult);
|
|
37125
|
+
if (!unknownCommitmentContent) {
|
|
37126
|
+
return requirements;
|
|
37127
|
+
}
|
|
37128
|
+
return appendSystemMessageSection(requirements, unknownCommitmentContent);
|
|
37129
|
+
}
|
|
37130
|
+
/**
|
|
37131
|
+
* Joins unknown commitment blocks into their final extra-context representation.
|
|
37132
|
+
*
|
|
37133
|
+
* @param parseResult - Parsed source including unknown commitment blocks.
|
|
37134
|
+
* @returns Unknown commitment source blocks in their original order.
|
|
37135
|
+
*
|
|
37136
|
+
* @private internal utility of `appendUnknownCommitmentContent`
|
|
37137
|
+
*/
|
|
37138
|
+
function getUnknownCommitmentContent(parseResult) {
|
|
37139
|
+
return parseResult.unknownCommitments
|
|
37140
|
+
.map((commitment) => commitment.source)
|
|
37141
|
+
.filter(Boolean)
|
|
37142
|
+
.join('\n\n');
|
|
37143
|
+
}
|
|
36926
37144
|
/**
|
|
36927
37145
|
* Collects plain-text lines that were not parsed as commitments and should still become part of the final system message.
|
|
36928
37146
|
*
|
|
@@ -39663,24 +39881,12 @@ const DEFAULT_CODER_PROMPT_TEMPLATE_DEFINITIONS = [
|
|
|
39663
39881
|
- @@@
|
|
39664
39882
|
- Keep in mind the DRY _(don't repeat yourself)_ principle.
|
|
39665
39883
|
- Do a proper analysis of the current functionality before you start implementing.
|
|
39666
|
-
- Add the changes into the [changelog](
|
|
39884
|
+
- Add the changes into the [changelog](CHANGELOG.md)
|
|
39885
|
+
- Update the [README](README.md) if needed.
|
|
39886
|
+
- Update the [AGENTS.md](AGENTS.md) for the next job to be done if it makes sense.
|
|
39667
39887
|
`),
|
|
39668
39888
|
isDefaultProjectTemplate: true,
|
|
39669
39889
|
},
|
|
39670
|
-
{
|
|
39671
|
-
id: 'agents-server',
|
|
39672
|
-
relativeFilePath: join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'agents-server.md'),
|
|
39673
|
-
slugPrefix: 'agents-server',
|
|
39674
|
-
content: spaceTrim$1(`
|
|
39675
|
-
- @@@
|
|
39676
|
-
- Keep in mind the DRY _(don't repeat yourself)_ principle.
|
|
39677
|
-
- Do a proper analysis of the current functionality before you start implementing.
|
|
39678
|
-
- You are working with the [Agents Server](apps/agents-server)
|
|
39679
|
-
- If you need to do the database migration, do it
|
|
39680
|
-
- Add the changes into the [changelog](changelog/_current-preversion.md)
|
|
39681
|
-
`),
|
|
39682
|
-
isDefaultProjectTemplate: false,
|
|
39683
|
-
},
|
|
39684
39890
|
];
|
|
39685
39891
|
/**
|
|
39686
39892
|
* Project-agnostic coder templates that `ptbk coder init` should materialize in any repository.
|
|
@@ -40772,6 +40978,10 @@ async function $applyHarnessInstallationStatus(status) {
|
|
|
40772
40978
|
console.info(colors.gray(`✔ ${definition.label} ${installedVersion} is up to date.`));
|
|
40773
40979
|
return;
|
|
40774
40980
|
}
|
|
40981
|
+
if (installationState === 'installed') {
|
|
40982
|
+
console.info(colors.gray(`✔ ${definition.label} ${installedVersion} is installed. Skipped checking for updates.`));
|
|
40983
|
+
return;
|
|
40984
|
+
}
|
|
40775
40985
|
if (installationState === 'unknown') {
|
|
40776
40986
|
console.info(colors.gray(`✔ ${definition.label} ${installedVersion} is installed, the newest version could not be checked.`));
|
|
40777
40987
|
return;
|
|
@@ -40985,20 +41195,20 @@ function comparePrereleaseIdentifier(firstIdentifier, secondIdentifier) {
|
|
|
40985
41195
|
// Note: [🟡] Code for CLI npm package version comparison [isNpmPackageVersionOutdated](src/cli/cli-commands/common/npm/isNpmPackageVersionOutdated.ts) should never be published outside of `@promptbook/cli`
|
|
40986
41196
|
|
|
40987
41197
|
/**
|
|
40988
|
-
* Detects whether one CLI coding harness is installed globally and whether it is up to date.
|
|
41198
|
+
* Detects whether one CLI coding harness is installed globally and, when enabled, whether it is up to date.
|
|
40989
41199
|
*
|
|
40990
|
-
* Note: `$` is used to indicate that this function is not a pure function - it runs the harness command and
|
|
41200
|
+
* Note: `$` is used to indicate that this function is not a pure function - it runs the harness command and may query npm
|
|
40991
41201
|
*
|
|
40992
41202
|
* @private internal utility of `promptbookCli`
|
|
40993
41203
|
*/
|
|
40994
|
-
async function $checkHarnessInstallation(definition) {
|
|
41204
|
+
async function $checkHarnessInstallation(definition, isHarnessUpdateCheckEnabled = true) {
|
|
40995
41205
|
const [installedVersion, latestVersion] = await Promise.all([
|
|
40996
41206
|
$resolveInstalledHarnessVersion(definition),
|
|
40997
|
-
$resolveLatestNpmPackageVersion(definition.npmPackageName),
|
|
41207
|
+
isHarnessUpdateCheckEnabled ? $resolveLatestNpmPackageVersion(definition.npmPackageName) : Promise.resolve(null),
|
|
40998
41208
|
]);
|
|
40999
41209
|
return {
|
|
41000
41210
|
definition,
|
|
41001
|
-
installationState: resolveHarnessInstallationState(installedVersion, latestVersion),
|
|
41211
|
+
installationState: resolveHarnessInstallationState(installedVersion, latestVersion, isHarnessUpdateCheckEnabled),
|
|
41002
41212
|
installedVersion,
|
|
41003
41213
|
latestVersion,
|
|
41004
41214
|
};
|
|
@@ -41006,10 +41216,13 @@ async function $checkHarnessInstallation(definition) {
|
|
|
41006
41216
|
/**
|
|
41007
41217
|
* Derives the installation state from the detected versions.
|
|
41008
41218
|
*/
|
|
41009
|
-
function resolveHarnessInstallationState(installedVersion, latestVersion) {
|
|
41219
|
+
function resolveHarnessInstallationState(installedVersion, latestVersion, isHarnessUpdateCheckEnabled) {
|
|
41010
41220
|
if (installedVersion === null) {
|
|
41011
41221
|
return 'not-installed';
|
|
41012
41222
|
}
|
|
41223
|
+
if (!isHarnessUpdateCheckEnabled) {
|
|
41224
|
+
return 'installed';
|
|
41225
|
+
}
|
|
41013
41226
|
if (latestVersion === null) {
|
|
41014
41227
|
return 'unknown';
|
|
41015
41228
|
}
|
|
@@ -41020,8 +41233,8 @@ function resolveHarnessInstallationState(installedVersion, latestVersion) {
|
|
|
41020
41233
|
// Note: [🟡] Code for CLI harness installation check [$checkHarnessInstallation](src/cli/cli-commands/common/harness/$checkHarnessInstallation.ts) should never be published outside of `@promptbook/cli`
|
|
41021
41234
|
|
|
41022
41235
|
/**
|
|
41023
|
-
* Checks that every given CLI coding harness is installed globally and up to date
|
|
41024
|
-
* install
|
|
41236
|
+
* Checks that every given CLI coding harness is installed globally and, when enabled, up to date.
|
|
41237
|
+
* Offers to install missing harnesses and update outdated ones.
|
|
41025
41238
|
*
|
|
41026
41239
|
* Harness names which are `undefined`, for example when no `--harness` is selected in a dry run,
|
|
41027
41240
|
* are ignored so that every call site can pass its raw selection.
|
|
@@ -41030,13 +41243,13 @@ function resolveHarnessInstallationState(installedVersion, latestVersion) {
|
|
|
41030
41243
|
*
|
|
41031
41244
|
* @private internal utility of `promptbookCli`
|
|
41032
41245
|
*/
|
|
41033
|
-
async function $ensureHarnessInstallations(harnessNames) {
|
|
41246
|
+
async function $ensureHarnessInstallations(harnessNames, isHarnessUpdateCheckEnabled = true) {
|
|
41034
41247
|
const definitions = resolveCheckedHarnessDefinitions(harnessNames);
|
|
41035
41248
|
if (definitions.length === 0) {
|
|
41036
41249
|
return;
|
|
41037
41250
|
}
|
|
41038
41251
|
// Note: Detection of all harnesses runs in parallel, the questions have to be asked one by one
|
|
41039
|
-
const statuses = await Promise.all(definitions.map((definition) => $checkHarnessInstallation(definition)));
|
|
41252
|
+
const statuses = await Promise.all(definitions.map((definition) => $checkHarnessInstallation(definition, isHarnessUpdateCheckEnabled)));
|
|
41040
41253
|
for (const status of statuses) {
|
|
41041
41254
|
await $applyHarnessInstallationStatus(status);
|
|
41042
41255
|
}
|
|
@@ -41050,6 +41263,27 @@ function resolveCheckedHarnessDefinitions(harnessNames) {
|
|
|
41050
41263
|
}
|
|
41051
41264
|
// Note: [🟡] Code for CLI harness installation orchestration [$ensureHarnessInstallations](src/cli/cli-commands/common/harness/$ensureHarnessInstallations.ts) should never be published outside of `@promptbook/cli`
|
|
41052
41265
|
|
|
41266
|
+
/**
|
|
41267
|
+
* Registers the shared `--no-harness-update` option on a `ptbk coder` command that uses a coding harness.
|
|
41268
|
+
*
|
|
41269
|
+
* @private internal utility of `promptbookCli`
|
|
41270
|
+
*/
|
|
41271
|
+
function addHarnessUpdateOption(command) {
|
|
41272
|
+
command.option('--no-harness-update', 'Skip checking whether globally installed coding harnesses are up to date');
|
|
41273
|
+
}
|
|
41274
|
+
/**
|
|
41275
|
+
* Converts the Commander harness-update flag into the normalized harness-check option.
|
|
41276
|
+
*
|
|
41277
|
+
* @private internal utility of `promptbookCli`
|
|
41278
|
+
*/
|
|
41279
|
+
function normalizeHarnessUpdateCliOptions(cliOptions) {
|
|
41280
|
+
return {
|
|
41281
|
+
isHarnessUpdateCheckEnabled: cliOptions.harnessUpdate,
|
|
41282
|
+
};
|
|
41283
|
+
}
|
|
41284
|
+
// Note: [🟡] Code for CLI harness update options [harnessUpdateCliOptions](src/cli/cli-commands/common/harnessUpdateCliOptions.ts) should never be published outside of `@promptbook/cli`
|
|
41285
|
+
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
41286
|
+
|
|
41053
41287
|
/**
|
|
41054
41288
|
* Relative path to the Promptbook Coder quick-reference file initialized in project roots.
|
|
41055
41289
|
*
|
|
@@ -41612,14 +41846,16 @@ function $initializeCoderInitCommand(program) {
|
|
|
41612
41846
|
- CODING_AGENT_GIT_EMAIL
|
|
41613
41847
|
- CODING_AGENT_GIT_SIGNING_KEY
|
|
41614
41848
|
|
|
41615
|
-
Checks that the coding harnesses are installed globally and up to date:
|
|
41849
|
+
Checks that the coding harnesses are installed globally and up to date unless \`--no-harness-update\` is used:
|
|
41616
41850
|
${block(listCheckedHarnessLabels())}
|
|
41617
41851
|
|
|
41618
41852
|
${block(CODER_GIT_SYNC_DESCRIPTION)}
|
|
41619
41853
|
`));
|
|
41620
41854
|
addCoderGitSyncOptions(command);
|
|
41855
|
+
addHarnessUpdateOption(command);
|
|
41621
41856
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
41622
41857
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
41858
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
41623
41859
|
const projectPath = process.cwd();
|
|
41624
41860
|
// Note: Import the git synchronization dynamically to keep the CLI fast for runs without `--commit`
|
|
41625
41861
|
const { $commitCoderChanges, $startCoderGitSync } = await Promise.resolve().then(function () { return coderGitSync; });
|
|
@@ -41632,7 +41868,7 @@ function $initializeCoderInitCommand(program) {
|
|
|
41632
41868
|
commitScope,
|
|
41633
41869
|
commitMessage: 'Initialize Promptbook Coder',
|
|
41634
41870
|
});
|
|
41635
|
-
await $ensureHarnessInstallations(CODER_INIT_CHECKED_HARNESS_NAMES);
|
|
41871
|
+
await $ensureHarnessInstallations(CODER_INIT_CHECKED_HARNESS_NAMES, isHarnessUpdateCheckEnabled);
|
|
41636
41872
|
}));
|
|
41637
41873
|
}
|
|
41638
41874
|
/**
|
|
@@ -41671,13 +41907,16 @@ function $initializeCoderPingCommand(program) {
|
|
|
41671
41907
|
- Reports the answer of the harness, the response time and the reported usage
|
|
41672
41908
|
- Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
|
|
41673
41909
|
- Leaves the project exactly as it was — nothing is read, written, changed or committed
|
|
41910
|
+
- Checks that the selected harness is installed globally and up to date unless --no-harness-update is used
|
|
41674
41911
|
- Use --no-ui to stream the raw harness output instead of only the compact result
|
|
41675
41912
|
`));
|
|
41676
41913
|
addPromptRunnerSelectionOptions(command);
|
|
41914
|
+
addHarnessUpdateOption(command);
|
|
41677
41915
|
addPromptRunnerRuntimeOptions(command);
|
|
41678
41916
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
41679
41917
|
const runnerOptions = normalizePromptRunnerSelectionCliOptions(cliOptions, { isAgentRequired: true });
|
|
41680
|
-
|
|
41918
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
41919
|
+
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
41681
41920
|
// Note: Import the ping dynamically to avoid loading heavy dependencies until needed
|
|
41682
41921
|
const { pingCoderHarness } = await Promise.resolve().then(function () { return pingCoderHarness$1; });
|
|
41683
41922
|
const { printCoderPingResult } = await Promise.resolve().then(function () { return printCoderPingResult$1; });
|
|
@@ -42168,7 +42407,7 @@ function $initializeCoderRunCommand(program) {
|
|
|
42168
42407
|
- Optional --isolate runs every prompt in its own temporary git worktree and merges it back when verified
|
|
42169
42408
|
- Optional --preserve-logs keeps temp prompt/log artifacts after successful rounds
|
|
42170
42409
|
- Optional --no-ui keeps plain streaming console output for logging and debugging
|
|
42171
|
-
- Checks that the selected harness is installed globally and up to date before the first prompt
|
|
42410
|
+
- Checks that the selected harness is installed globally and up to date before the first prompt unless --no-harness-update is used
|
|
42172
42411
|
- In interactive mode, checks local and global Promptbook CLI installations and offers to update them
|
|
42173
42412
|
- Supports GPG signing of commits
|
|
42174
42413
|
- Optional pre-coding test run that can stop or repair pre-existing failures
|
|
@@ -42178,6 +42417,7 @@ function $initializeCoderRunCommand(program) {
|
|
|
42178
42417
|
`));
|
|
42179
42418
|
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
42180
42419
|
addPromptRunnerSelectionOptions(command);
|
|
42420
|
+
addHarnessUpdateOption(command);
|
|
42181
42421
|
command.option('--agent <agent-book-path>', 'Path to a .book file whose compiled system message is prepended to each coding prompt');
|
|
42182
42422
|
command.option('--context <context-or-file>', 'Append extra instructions either inline or from a file path relative to the current project');
|
|
42183
42423
|
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
@@ -42219,6 +42459,7 @@ function $initializeCoderRunCommand(program) {
|
|
|
42219
42459
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
42220
42460
|
isAgentRequired: !dryRun,
|
|
42221
42461
|
});
|
|
42462
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
42222
42463
|
// [1] Parse the wait options and --no-auto:
|
|
42223
42464
|
// default: run automatically through the queue (no waiting between prompts)
|
|
42224
42465
|
// --no-auto: wait for user confirmation before each prompt (interactive mode)
|
|
@@ -42229,7 +42470,7 @@ function $initializeCoderRunCommand(program) {
|
|
|
42229
42470
|
if (await $ensurePromptbookCliInstallations()) {
|
|
42230
42471
|
return process.exit(0);
|
|
42231
42472
|
}
|
|
42232
|
-
await $ensureHarnessInstallations([runnerOptions.agentName]);
|
|
42473
|
+
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
42233
42474
|
const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
|
|
42234
42475
|
const waitBetweenPrompts = parseOptionalWaitDuration(waitBetweenPromptsValue, 0);
|
|
42235
42476
|
const waitAfterError = parseOptionalWaitDuration(waitAfterErrorValue, DEFAULT_WAIT_AFTER_ERROR_MS$1);
|
|
@@ -42323,7 +42564,7 @@ function $initializeCoderServerCommand(program) {
|
|
|
42323
42564
|
|
|
42324
42565
|
Features:
|
|
42325
42566
|
- Runs the same prompt processing as \`ptbk coder run\`
|
|
42326
|
-
- Checks that the selected harness is installed globally and up to date on startup
|
|
42567
|
+
- Checks that the selected harness is installed globally and up to date on startup unless --no-harness-update is used
|
|
42327
42568
|
- Does not exit when all prompts are done; polls for new prompt files instead
|
|
42328
42569
|
- Serves a kanban board at http://localhost:<port> for visual progress tracking
|
|
42329
42570
|
- Allows editing prompt files directly from the browser (Trello-style)
|
|
@@ -42335,6 +42576,7 @@ function $initializeCoderServerCommand(program) {
|
|
|
42335
42576
|
.default(DEFAULT_CODER_SERVER_PORT));
|
|
42336
42577
|
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
42337
42578
|
addPromptRunnerSelectionOptions(command);
|
|
42579
|
+
addHarnessUpdateOption(command);
|
|
42338
42580
|
command.option('--agent <agent-book-path>', 'Path to a .book file whose compiled system message is prepended to each coding prompt');
|
|
42339
42581
|
command.option('--context <context-or-file>', 'Append extra instructions either inline or from a file path relative to the current project');
|
|
42340
42582
|
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
@@ -42366,7 +42608,8 @@ function $initializeCoderServerCommand(program) {
|
|
|
42366
42608
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
42367
42609
|
isAgentRequired: !dryRun,
|
|
42368
42610
|
});
|
|
42369
|
-
|
|
42611
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
42612
|
+
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
42370
42613
|
// [1] Parse the wait options and --no-auto (same logic as `coder run`)
|
|
42371
42614
|
const waitForUser = !auto;
|
|
42372
42615
|
const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
|
|
@@ -44290,23 +44533,27 @@ async function locateAppOnMacOs({ macOsName, }) {
|
|
|
44290
44533
|
// TODO: [🧠][♿] Maybe export through `@promptbook/node`
|
|
44291
44534
|
|
|
44292
44535
|
/**
|
|
44293
|
-
* Attempts to locate the specified application on a Windows system by searching common installation directories.
|
|
44536
|
+
* Attempts to locate the specified application on a Windows system by searching PATH and common installation directories.
|
|
44294
44537
|
* Returns the path to the executable if found, or null otherwise.
|
|
44295
44538
|
*
|
|
44296
44539
|
* @private within the repository
|
|
44297
44540
|
*/
|
|
44298
44541
|
async function locateAppOnWindows({ appName, windowsSuffix, }) {
|
|
44299
44542
|
try {
|
|
44300
|
-
const
|
|
44543
|
+
const EXECUTABLE_FILENAME = windowsSuffix.replace(/^.*[\\/]/, '');
|
|
44544
|
+
const PATH_EXECUTABLE_PATHS = (process.env.PATH || '')
|
|
44545
|
+
.split(delimiter)
|
|
44546
|
+
.filter(Boolean)
|
|
44547
|
+
.map((pathPrefix) => join(pathPrefix, EXECUTABLE_FILENAME));
|
|
44548
|
+
const INSTALLATION_EXECUTABLE_PATHS = [
|
|
44301
44549
|
process.env.LOCALAPPDATA,
|
|
44302
44550
|
join(process.env.LOCALAPPDATA || '', 'Programs'),
|
|
44303
44551
|
process.env.PROGRAMFILES,
|
|
44304
44552
|
process.env['PROGRAMFILES(X86)'],
|
|
44305
|
-
];
|
|
44306
|
-
for (const
|
|
44307
|
-
|
|
44308
|
-
|
|
44309
|
-
return path;
|
|
44553
|
+
].map((pathPrefix) => pathPrefix + windowsSuffix);
|
|
44554
|
+
for (const executablePath of [...PATH_EXECUTABLE_PATHS, ...INSTALLATION_EXECUTABLE_PATHS]) {
|
|
44555
|
+
if (await isExecutable(executablePath, $provideFilesystemForNode())) {
|
|
44556
|
+
return executablePath;
|
|
44310
44557
|
}
|
|
44311
44558
|
}
|
|
44312
44559
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|
|
@@ -75699,6 +75946,10 @@ async function runTestBefore(options) {
|
|
|
75699
75946
|
* Constant for prompts dir.
|
|
75700
75947
|
*/
|
|
75701
75948
|
const PROMPTS_DIR$1 = join(process.cwd(), 'prompts');
|
|
75949
|
+
/**
|
|
75950
|
+
* Commit message for files changed by a successful or failed pre-coding test in repair mode.
|
|
75951
|
+
*/
|
|
75952
|
+
const PRE_CODING_TEST_CHANGES_COMMIT_MESSAGE = 'test: Apply changes made by pre-coding tests';
|
|
75702
75953
|
/**
|
|
75703
75954
|
* Main entry point for running prompts with the selected agent.
|
|
75704
75955
|
*
|
|
@@ -76022,6 +76273,7 @@ async function runTestBeforeIfNeeded(options) {
|
|
|
76022
76273
|
});
|
|
76023
76274
|
await ensureWorkingTreeClean();
|
|
76024
76275
|
}
|
|
76276
|
+
const testBeforeCommitScope = await captureTestBeforeCommitScopeIfNeeded(runOptions);
|
|
76025
76277
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
76026
76278
|
const testBeforeResult = await runTestBefore({
|
|
76027
76279
|
testCommand: runOptions.testCommand,
|
|
@@ -76030,6 +76282,11 @@ async function runTestBeforeIfNeeded(options) {
|
|
|
76030
76282
|
}).finally(() => {
|
|
76031
76283
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
76032
76284
|
});
|
|
76285
|
+
await commitTestBeforeChangesIfNeeded({
|
|
76286
|
+
runOptions,
|
|
76287
|
+
testBeforeCommitScope,
|
|
76288
|
+
waitForRequestedPause,
|
|
76289
|
+
});
|
|
76033
76290
|
if (testBeforeResult.isPassed) {
|
|
76034
76291
|
return hasWaitedForStart;
|
|
76035
76292
|
}
|
|
@@ -76078,6 +76335,38 @@ async function runTestBeforeIfNeeded(options) {
|
|
|
76078
76335
|
});
|
|
76079
76336
|
return updatedHasWaitedForStart;
|
|
76080
76337
|
}
|
|
76338
|
+
/**
|
|
76339
|
+
* Captures the files present before a `yes-and-fix` pre-coding test, so only changes made by that test can be committed.
|
|
76340
|
+
*/
|
|
76341
|
+
async function captureTestBeforeCommitScopeIfNeeded(runOptions) {
|
|
76342
|
+
if (runOptions.testBefore !== 'yes-and-fix' || runOptions.noCommit) {
|
|
76343
|
+
return undefined;
|
|
76344
|
+
}
|
|
76345
|
+
return captureCoderCommitScope(process.cwd());
|
|
76346
|
+
}
|
|
76347
|
+
/**
|
|
76348
|
+
* Commits files changed by a `yes-and-fix` pre-coding test before the coder continues to a queued or repair prompt.
|
|
76349
|
+
*/
|
|
76350
|
+
async function commitTestBeforeChangesIfNeeded(options) {
|
|
76351
|
+
const { runOptions, testBeforeCommitScope, waitForRequestedPause } = options;
|
|
76352
|
+
if (!testBeforeCommitScope) {
|
|
76353
|
+
return;
|
|
76354
|
+
}
|
|
76355
|
+
const relevantPaths = await resolveCoderCommitScopePaths(testBeforeCommitScope);
|
|
76356
|
+
if (relevantPaths.length === 0) {
|
|
76357
|
+
return;
|
|
76358
|
+
}
|
|
76359
|
+
await waitForRequestedPause({
|
|
76360
|
+
checkpointLabel: 'committing changes made by pre-coding tests',
|
|
76361
|
+
phase: 'verifying',
|
|
76362
|
+
statusMessage: 'Committing changes made by pre-coding tests...',
|
|
76363
|
+
});
|
|
76364
|
+
await commitChanges(PRE_CODING_TEST_CHANGES_COMMIT_MESSAGE, {
|
|
76365
|
+
autoPush: runOptions.autoPush,
|
|
76366
|
+
projectPath: testBeforeCommitScope.projectPath,
|
|
76367
|
+
relevantPaths,
|
|
76368
|
+
});
|
|
76369
|
+
}
|
|
76081
76370
|
/**
|
|
76082
76371
|
* Creates a pause waiter that keeps the progress display and rich UI in sync.
|
|
76083
76372
|
*/
|