@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/umd/index.umd.js
CHANGED
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
* @generated
|
|
59
59
|
* @see https://github.com/webgptorg/promptbook
|
|
60
60
|
*/
|
|
61
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-
|
|
61
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-12';
|
|
62
62
|
/**
|
|
63
63
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
64
64
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -20317,6 +20317,30 @@
|
|
|
20317
20317
|
// TODO: [🧠] Maybe create through standardized $register
|
|
20318
20318
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
20319
20319
|
|
|
20320
|
+
/**
|
|
20321
|
+
* Pattern shared by Book parsing and editor highlighting for a commitment-like line.
|
|
20322
|
+
*
|
|
20323
|
+
* A Book commitment keyword consists of one or more all-uppercase words with at least
|
|
20324
|
+
* two characters each. This deliberately mirrors the Book editor syntax rule so an
|
|
20325
|
+
* unknown keyword starts a new source block everywhere it is interpreted.
|
|
20326
|
+
*
|
|
20327
|
+
* @private internal constant of `getBookCommitmentLineType`
|
|
20328
|
+
*/
|
|
20329
|
+
const BOOK_COMMITMENT_LINE_TYPE_REGEX = /^\s*(?<type>[A-Z][A-Z0-9]+(?:\s+[A-Z][A-Z0-9]+)*)(?=\s|$)/;
|
|
20330
|
+
/**
|
|
20331
|
+
* Extracts the uppercase commitment type from a Book line, including types not registered by Promptbook.
|
|
20332
|
+
*
|
|
20333
|
+
* @param line - One raw Book source line.
|
|
20334
|
+
* @returns Matched commitment type or `null` when the line does not begin with commitment syntax.
|
|
20335
|
+
*
|
|
20336
|
+
* @private internal utility of Book parsing and `<BookEditor/>`
|
|
20337
|
+
*/
|
|
20338
|
+
function getBookCommitmentLineType(line) {
|
|
20339
|
+
var _a;
|
|
20340
|
+
const match = BOOK_COMMITMENT_LINE_TYPE_REGEX.exec(line);
|
|
20341
|
+
return ((_a = match === null || match === void 0 ? void 0 : match.groups) === null || _a === void 0 ? void 0 : _a.type) || null;
|
|
20342
|
+
}
|
|
20343
|
+
|
|
20320
20344
|
/**
|
|
20321
20345
|
* Consumes the agent-name prelude from raw source.
|
|
20322
20346
|
*
|
|
@@ -20374,13 +20398,15 @@
|
|
|
20374
20398
|
return {
|
|
20375
20399
|
agentName: null,
|
|
20376
20400
|
commitments: [],
|
|
20401
|
+
unknownCommitments: [],
|
|
20377
20402
|
nonCommitmentLines: [],
|
|
20378
20403
|
};
|
|
20379
20404
|
}
|
|
20380
20405
|
const { lines, agentName, agentNameLineIndex, agentNameLineNumber } = parseAgentSourcePrelude(agentSource);
|
|
20381
20406
|
const commitments = [];
|
|
20407
|
+
const unknownCommitments = [];
|
|
20382
20408
|
const nonCommitmentLines = agentNameLineIndex >= 0 ? [lines[agentNameLineIndex]] : [];
|
|
20383
|
-
// Parse commitments with multiline support
|
|
20409
|
+
// Parse commitments with multiline support.
|
|
20384
20410
|
let currentCommitment = null;
|
|
20385
20411
|
// Process lines starting from after the agent name line
|
|
20386
20412
|
const startIndex = agentNameLineIndex >= 0 ? agentNameLineIndex + 1 : 0;
|
|
@@ -20394,25 +20420,11 @@
|
|
|
20394
20420
|
// Check if this line starts or ends a code block
|
|
20395
20421
|
if (trimmedLine.startsWith('```')) {
|
|
20396
20422
|
isInsideCodeBlock = !isInsideCodeBlock;
|
|
20397
|
-
|
|
20398
|
-
// If we are inside a commitment, the code block is part of it
|
|
20399
|
-
currentCommitment.contentLines.push(line);
|
|
20400
|
-
}
|
|
20401
|
-
else {
|
|
20402
|
-
// If we are not inside a commitment, the code block is non-commitment
|
|
20403
|
-
nonCommitmentLines.push(line);
|
|
20404
|
-
}
|
|
20423
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
20405
20424
|
continue;
|
|
20406
20425
|
}
|
|
20407
20426
|
if (isInsideCodeBlock) {
|
|
20408
|
-
|
|
20409
|
-
// If we are inside a commitment and a code block, the line is part of the commitment
|
|
20410
|
-
currentCommitment.contentLines.push(line);
|
|
20411
|
-
}
|
|
20412
|
-
else {
|
|
20413
|
-
// If we are inside a code block but not a commitment, the line is non-commitment
|
|
20414
|
-
nonCommitmentLines.push(line);
|
|
20415
|
-
}
|
|
20427
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
20416
20428
|
continue;
|
|
20417
20429
|
}
|
|
20418
20430
|
// Check if this line starts a new commitment
|
|
@@ -20421,22 +20433,14 @@
|
|
|
20421
20433
|
const typeRegex = definition.createTypeRegex();
|
|
20422
20434
|
const match = typeRegex.exec(line.trim());
|
|
20423
20435
|
if (match && ((_a = match.groups) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
20424
|
-
|
|
20425
|
-
if (currentCommitment) {
|
|
20426
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
20427
|
-
commitments.push({
|
|
20428
|
-
type: currentCommitment.type,
|
|
20429
|
-
content: _spaceTrim.spaceTrim(fullContent),
|
|
20430
|
-
originalLine: currentCommitment.originalStartLine,
|
|
20431
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
20432
|
-
});
|
|
20433
|
-
}
|
|
20436
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20434
20437
|
// Extract the initial content from the commitment line
|
|
20435
20438
|
const fullRegex = definition.createRegex();
|
|
20436
20439
|
const fullMatch = fullRegex.exec(line.trim());
|
|
20437
20440
|
const initialContent = ((_b = fullMatch === null || fullMatch === void 0 ? void 0 : fullMatch.groups) === null || _b === void 0 ? void 0 : _b.contents) || '';
|
|
20438
20441
|
// Start a new commitment
|
|
20439
20442
|
currentCommitment = {
|
|
20443
|
+
kind: 'known',
|
|
20440
20444
|
type: definition.type,
|
|
20441
20445
|
startLineNumber: i + 1,
|
|
20442
20446
|
originalStartLine: line,
|
|
@@ -20446,52 +20450,90 @@
|
|
|
20446
20450
|
break;
|
|
20447
20451
|
}
|
|
20448
20452
|
}
|
|
20453
|
+
if (foundNewCommitment) {
|
|
20454
|
+
continue;
|
|
20455
|
+
}
|
|
20456
|
+
const unknownCommitmentType = getBookCommitmentLineType(line);
|
|
20457
|
+
if (unknownCommitmentType) {
|
|
20458
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20459
|
+
currentCommitment = {
|
|
20460
|
+
kind: 'unknown',
|
|
20461
|
+
type: unknownCommitmentType,
|
|
20462
|
+
startLineNumber: i + 1,
|
|
20463
|
+
originalStartLine: line,
|
|
20464
|
+
sourceLines: [line],
|
|
20465
|
+
};
|
|
20466
|
+
continue;
|
|
20467
|
+
}
|
|
20449
20468
|
// Check if this is a horizontal line (ends any current commitment)
|
|
20450
20469
|
const isHorizontalLine = HORIZONTAL_LINE_PATTERN$1.test(line);
|
|
20451
20470
|
if (isHorizontalLine) {
|
|
20452
|
-
|
|
20453
|
-
|
|
20454
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
20455
|
-
commitments.push({
|
|
20456
|
-
type: currentCommitment.type,
|
|
20457
|
-
content: _spaceTrim.spaceTrim(fullContent),
|
|
20458
|
-
originalLine: currentCommitment.originalStartLine,
|
|
20459
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
20460
|
-
});
|
|
20461
|
-
currentCommitment = null;
|
|
20462
|
-
}
|
|
20471
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20472
|
+
currentCommitment = null;
|
|
20463
20473
|
// Add horizontal line to non-commitment lines
|
|
20464
20474
|
nonCommitmentLines.push(line);
|
|
20465
20475
|
continue;
|
|
20466
20476
|
}
|
|
20467
|
-
|
|
20468
|
-
if (currentCommitment) {
|
|
20469
|
-
// This line belongs to the current commitment
|
|
20470
|
-
currentCommitment.contentLines.push(line);
|
|
20471
|
-
}
|
|
20472
|
-
else {
|
|
20473
|
-
// This line is not part of any commitment
|
|
20474
|
-
nonCommitmentLines.push(line);
|
|
20475
|
-
}
|
|
20476
|
-
}
|
|
20477
|
-
}
|
|
20478
|
-
// Don't forget to save the last commitment if it exists
|
|
20479
|
-
if (currentCommitment) {
|
|
20480
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
20481
|
-
commitments.push({
|
|
20482
|
-
type: currentCommitment.type,
|
|
20483
|
-
content: _spaceTrim.spaceTrim(fullContent),
|
|
20484
|
-
originalLine: currentCommitment.originalStartLine,
|
|
20485
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
20486
|
-
});
|
|
20477
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
20487
20478
|
}
|
|
20479
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
20488
20480
|
return {
|
|
20489
20481
|
agentName,
|
|
20490
20482
|
agentNameLineNumber,
|
|
20491
20483
|
commitments,
|
|
20484
|
+
unknownCommitments,
|
|
20492
20485
|
nonCommitmentLines,
|
|
20493
20486
|
};
|
|
20494
20487
|
}
|
|
20488
|
+
/**
|
|
20489
|
+
* Stores the current known or unknown commitment in its appropriate parsed collection.
|
|
20490
|
+
*
|
|
20491
|
+
* @param currentCommitment - Commitment-like block collected so far.
|
|
20492
|
+
* @param commitments - Parsed registered commitments to append to.
|
|
20493
|
+
* @param unknownCommitments - Parsed unregistered commitments to append to.
|
|
20494
|
+
*
|
|
20495
|
+
* @private internal utility of `parseAgentSourceWithCommitments`
|
|
20496
|
+
*/
|
|
20497
|
+
function appendCurrentCommitment(currentCommitment, commitments, unknownCommitments) {
|
|
20498
|
+
if (!currentCommitment) {
|
|
20499
|
+
return;
|
|
20500
|
+
}
|
|
20501
|
+
if (currentCommitment.kind === 'unknown') {
|
|
20502
|
+
unknownCommitments.push({
|
|
20503
|
+
type: currentCommitment.type,
|
|
20504
|
+
originalLine: currentCommitment.originalStartLine,
|
|
20505
|
+
lineNumber: currentCommitment.startLineNumber,
|
|
20506
|
+
source: _spaceTrim.spaceTrim(currentCommitment.sourceLines.join('\n')),
|
|
20507
|
+
});
|
|
20508
|
+
return;
|
|
20509
|
+
}
|
|
20510
|
+
commitments.push({
|
|
20511
|
+
type: currentCommitment.type,
|
|
20512
|
+
content: _spaceTrim.spaceTrim(currentCommitment.contentLines.join('\n')),
|
|
20513
|
+
originalLine: currentCommitment.originalStartLine,
|
|
20514
|
+
lineNumber: currentCommitment.startLineNumber,
|
|
20515
|
+
});
|
|
20516
|
+
}
|
|
20517
|
+
/**
|
|
20518
|
+
* Adds one source line to the active commitment-like block, or to plain source content when none is active.
|
|
20519
|
+
*
|
|
20520
|
+
* @param currentCommitment - Commitment-like block currently being collected.
|
|
20521
|
+
* @param line - Source line to append.
|
|
20522
|
+
* @param nonCommitmentLines - Plain source lines to append to when no block is active.
|
|
20523
|
+
*
|
|
20524
|
+
* @private internal utility of `parseAgentSourceWithCommitments`
|
|
20525
|
+
*/
|
|
20526
|
+
function appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines) {
|
|
20527
|
+
if (!currentCommitment) {
|
|
20528
|
+
nonCommitmentLines.push(line);
|
|
20529
|
+
return;
|
|
20530
|
+
}
|
|
20531
|
+
if (currentCommitment.kind === 'unknown') {
|
|
20532
|
+
currentCommitment.sourceLines.push(line);
|
|
20533
|
+
return;
|
|
20534
|
+
}
|
|
20535
|
+
currentCommitment.contentLines.push(line);
|
|
20536
|
+
}
|
|
20495
20537
|
|
|
20496
20538
|
/**
|
|
20497
20539
|
* Parses parameters from text using both supported notations:
|
|
@@ -24761,14 +24803,90 @@
|
|
|
24761
24803
|
* without the generated script and the prompt it embeds.
|
|
24762
24804
|
*/
|
|
24763
24805
|
const SCRIPT_EXECUTION_LOG_RAW_OUTPUT_MARKER = '--- raw output ---';
|
|
24806
|
+
/**
|
|
24807
|
+
* Command which terminates the Bash process tree rooted at the running harness.
|
|
24808
|
+
*
|
|
24809
|
+
* Bash's POSIX process IDs differ from Windows process IDs in Git Bash, so the Windows branch resolves the native PID
|
|
24810
|
+
* before delegating to `taskkill`. Unix harnesses run in a dedicated Bash job process group, which can be terminated
|
|
24811
|
+
* with its negative process ID.
|
|
24812
|
+
*/
|
|
24813
|
+
const TERMINATE_BASH_PROCESS_TREE_COMMAND = process.platform === 'win32'
|
|
24814
|
+
? _spaceTrim.spaceTrim(`
|
|
24815
|
+
HARNESS_WINDOWS_PROCESS_ID="$(ps -l -p "$HARNESS_PROCESS_ID" | awk 'NR == 2 { print $4 }')"
|
|
24816
|
+
if [ -n "$HARNESS_WINDOWS_PROCESS_ID" ]; then
|
|
24817
|
+
MSYS_NO_PATHCONV=1 taskkill.exe /PID "$HARNESS_WINDOWS_PROCESS_ID" /T /F > /dev/null 2>&1 || true
|
|
24818
|
+
fi
|
|
24819
|
+
`)
|
|
24820
|
+
: 'kill -TERM -- "-$HARNESS_PROCESS_ID" 2>/dev/null || true';
|
|
24821
|
+
/**
|
|
24822
|
+
* Shell condition that detects whether the Node process which owns the harness is still running.
|
|
24823
|
+
*
|
|
24824
|
+
* Git Bash translates process IDs and command switches, so querying the native Windows PID needs both `tasklist` and
|
|
24825
|
+
* disabled MSYS path conversion there. Unix can use the native `kill -0` process existence check.
|
|
24826
|
+
*/
|
|
24827
|
+
const IS_PARENT_PROCESS_RUNNING_CONDITION = process.platform === 'win32'
|
|
24828
|
+
? '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 }\''
|
|
24829
|
+
: 'kill -0 "$PARENT_CODER_PROCESS_ID" 2>/dev/null';
|
|
24830
|
+
/**
|
|
24831
|
+
* Environment variable that identifies the Node process responsible for a temporary harness shell.
|
|
24832
|
+
*/
|
|
24833
|
+
const PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME = 'PTBK_CODER_PARENT_PROCESS_ID';
|
|
24764
24834
|
/**
|
|
24765
24835
|
* Small bash wrapper that preserves stdout/stderr streams while teeing both into the runtime log file.
|
|
24836
|
+
*
|
|
24837
|
+
* A watcher polls the owning Node process by its PID. If that process exits abruptly, the watcher stops the whole
|
|
24838
|
+
* Bash and harness process tree instead of letting it continue as an orphan.
|
|
24766
24839
|
*/
|
|
24767
24840
|
const LOGGED_BASH_WRAPPER_COMMAND = _spaceTrim.spaceTrim(`
|
|
24841
|
+
PARENT_CODER_PROCESS_ID="\${${PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME}}"
|
|
24842
|
+
unset ${PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME}
|
|
24843
|
+
|
|
24844
|
+
terminate_harness_process_tree() {
|
|
24845
|
+
# Keep the EXIT cleanup intact so the wrapper can also stop its parent-process watcher.
|
|
24846
|
+
trap - HUP INT TERM
|
|
24847
|
+
${TERMINATE_BASH_PROCESS_TREE_COMMAND}
|
|
24848
|
+
}
|
|
24849
|
+
|
|
24850
|
+
is_parent_process_running() {
|
|
24851
|
+
${IS_PARENT_PROCESS_RUNNING_CONDITION}
|
|
24852
|
+
}
|
|
24853
|
+
|
|
24768
24854
|
if [ -n "\${${PTBK_CODER_LOG_FILE_ENV_NAME}:-}" ]; then
|
|
24769
|
-
exec > >(tee -a "
|
|
24855
|
+
exec > >(tee -a "$${PTBK_CODER_LOG_FILE_ENV_NAME}") 2> >(tee -a "$${PTBK_CODER_LOG_FILE_ENV_NAME}" >&2)
|
|
24770
24856
|
fi
|
|
24771
|
-
|
|
24857
|
+
|
|
24858
|
+
watch_parent_process() {
|
|
24859
|
+
trap 'exit 0' HUP INT TERM
|
|
24860
|
+
|
|
24861
|
+
while is_parent_process_running; do
|
|
24862
|
+
sleep 1
|
|
24863
|
+
done
|
|
24864
|
+
|
|
24865
|
+
terminate_harness_process_tree
|
|
24866
|
+
}
|
|
24867
|
+
|
|
24868
|
+
# Background harness jobs need their own process group on Unix so termination cannot reach the parent coder.
|
|
24869
|
+
set -m
|
|
24870
|
+
if ! is_parent_process_running; then
|
|
24871
|
+
exit 1
|
|
24872
|
+
fi
|
|
24873
|
+
bash "$1" &
|
|
24874
|
+
HARNESS_PROCESS_ID=$!
|
|
24875
|
+
|
|
24876
|
+
cleanup_parent_process_watcher() {
|
|
24877
|
+
kill "$PARENT_PROCESS_WATCHER_PID" 2>/dev/null || true
|
|
24878
|
+
wait "$PARENT_PROCESS_WATCHER_PID" 2>/dev/null || true
|
|
24879
|
+
}
|
|
24880
|
+
|
|
24881
|
+
watch_parent_process &
|
|
24882
|
+
PARENT_PROCESS_WATCHER_PID=$!
|
|
24883
|
+
|
|
24884
|
+
trap cleanup_parent_process_watcher EXIT
|
|
24885
|
+
trap terminate_harness_process_tree HUP INT TERM
|
|
24886
|
+
|
|
24887
|
+
wait "$HARNESS_PROCESS_ID"
|
|
24888
|
+
SCRIPT_EXIT_CODE=$?
|
|
24889
|
+
exit "$SCRIPT_EXIT_CODE"
|
|
24772
24890
|
`);
|
|
24773
24891
|
/**
|
|
24774
24892
|
* Shapes one bash invocation that optionally mirrors live script output into a temporary log file.
|
|
@@ -24824,6 +24942,38 @@
|
|
|
24824
24942
|
return scriptPath.toLowerCase().endsWith('.test.sh') ? 'test shell' : 'runner shell';
|
|
24825
24943
|
}
|
|
24826
24944
|
|
|
24945
|
+
/**
|
|
24946
|
+
* Standard streams used by every temporary Bash runner.
|
|
24947
|
+
*/
|
|
24948
|
+
const BASH_PROCESS_STDIO = ['pipe', 'pipe', 'pipe'];
|
|
24949
|
+
/**
|
|
24950
|
+
* Whether the current Node process is running on Windows.
|
|
24951
|
+
*/
|
|
24952
|
+
const IS_WINDOWS$1 = process.platform === 'win32';
|
|
24953
|
+
/**
|
|
24954
|
+
* Starts one temporary Bash script in a process tree owned by the current Node process.
|
|
24955
|
+
*
|
|
24956
|
+
* The wrapper watches the supplied owning process ID. When that process exits abruptly, the wrapper terminates every
|
|
24957
|
+
* nested shell and harness process instead of leaving it orphaned.
|
|
24958
|
+
*
|
|
24959
|
+
* @private internal utility of the coding prompt runner
|
|
24960
|
+
*/
|
|
24961
|
+
function $spawnLoggedBashScript(options) {
|
|
24962
|
+
var _a;
|
|
24963
|
+
const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
|
|
24964
|
+
const parentProcessId = (_a = options.parentProcessId) !== null && _a !== void 0 ? _a : process.pid;
|
|
24965
|
+
return child_process.spawn('bash', bashExecution.args, {
|
|
24966
|
+
detached: !IS_WINDOWS$1,
|
|
24967
|
+
env: {
|
|
24968
|
+
...process.env,
|
|
24969
|
+
...bashExecution.env,
|
|
24970
|
+
[PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME]: parentProcessId.toString(),
|
|
24971
|
+
},
|
|
24972
|
+
stdio: BASH_PROCESS_STDIO,
|
|
24973
|
+
windowsHide: true,
|
|
24974
|
+
});
|
|
24975
|
+
}
|
|
24976
|
+
|
|
24827
24977
|
/**
|
|
24828
24978
|
* Prints one live shell output chunk to the terminal when console mirroring is enabled.
|
|
24829
24979
|
*/
|
|
@@ -24846,12 +24996,12 @@
|
|
|
24846
24996
|
async function runBashScriptWithOutput(options) {
|
|
24847
24997
|
var _a;
|
|
24848
24998
|
await appendScriptExecutionLogStart(options);
|
|
24849
|
-
const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
|
|
24850
24999
|
const scriptPathPosix = toPosixPath(options.scriptPath);
|
|
24851
25000
|
const shouldPrintLiveOutput = (_a = options.shouldPrintLiveOutput) !== null && _a !== void 0 ? _a : true;
|
|
24852
25001
|
return await new Promise((resolve, reject) => {
|
|
24853
|
-
const commandProcess =
|
|
24854
|
-
|
|
25002
|
+
const commandProcess = $spawnLoggedBashScript({
|
|
25003
|
+
scriptPath: options.scriptPath,
|
|
25004
|
+
logPath: options.logPath,
|
|
24855
25005
|
});
|
|
24856
25006
|
let output = '';
|
|
24857
25007
|
let settled = false;
|
|
@@ -24910,8 +25060,9 @@
|
|
|
24910
25060
|
const failure = new Error(_spaceTrim.spaceTrim(output) || `Command "bash ${scriptPathPosix}" exited with code ${code}`);
|
|
24911
25061
|
settleWithLog(`failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`, () => reject(failure), failure);
|
|
24912
25062
|
};
|
|
25063
|
+
// Wait for `close`, not only `exit`, because the Bash wrapper can still be flushing its tee process
|
|
25064
|
+
// substitutions after the direct shell exits.
|
|
24913
25065
|
commandProcess.on('close', handleExit);
|
|
24914
|
-
commandProcess.on('exit', handleExit);
|
|
24915
25066
|
commandProcess.on('disconnect', () => {
|
|
24916
25067
|
const failure = new Error(`Command "bash ${scriptPathPosix}" disconnected`);
|
|
24917
25068
|
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
@@ -25772,6 +25923,35 @@
|
|
|
25772
25923
|
error.message.includes('bin/node'));
|
|
25773
25924
|
}
|
|
25774
25925
|
|
|
25926
|
+
/**
|
|
25927
|
+
* Whether the current coder process runs on Windows.
|
|
25928
|
+
*/
|
|
25929
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
25930
|
+
/**
|
|
25931
|
+
* Stops one active temporary Bash shell together with the harness process tree it owns.
|
|
25932
|
+
*
|
|
25933
|
+
* Unix sends `SIGTERM` to the wrapper so its shell trap terminates the separately grouped harness job. Windows does
|
|
25934
|
+
* not reliably deliver that signal to Bash, so the native `taskkill` command terminates the direct shell tree instead.
|
|
25935
|
+
*
|
|
25936
|
+
* @private internal utility of the coding prompt runner
|
|
25937
|
+
*/
|
|
25938
|
+
function $terminateLoggedBashProcessTree(commandProcess) {
|
|
25939
|
+
if (commandProcess.exitCode !== null || commandProcess.signalCode !== null) {
|
|
25940
|
+
return;
|
|
25941
|
+
}
|
|
25942
|
+
if (!IS_WINDOWS) {
|
|
25943
|
+
commandProcess.kill('SIGTERM');
|
|
25944
|
+
return;
|
|
25945
|
+
}
|
|
25946
|
+
if (!commandProcess.pid) {
|
|
25947
|
+
return;
|
|
25948
|
+
}
|
|
25949
|
+
child_process.spawnSync('taskkill.exe', ['/PID', commandProcess.pid.toString(), '/T', '/F'], {
|
|
25950
|
+
stdio: 'ignore',
|
|
25951
|
+
windowsHide: true,
|
|
25952
|
+
});
|
|
25953
|
+
}
|
|
25954
|
+
|
|
25775
25955
|
/**
|
|
25776
25956
|
* Maximum number of output characters included in thrown error messages.
|
|
25777
25957
|
*/
|
|
@@ -25814,15 +25994,16 @@
|
|
|
25814
25994
|
const scriptPathPosix = toPosixPath(scriptPath);
|
|
25815
25995
|
const shouldPrintLiveOutput = (_a = options.shouldPrintLiveOutput) !== null && _a !== void 0 ? _a : true;
|
|
25816
25996
|
await appendScriptExecutionLogStart(options);
|
|
25817
|
-
const bashExecution = buildLoggedBashExecution(scriptPath, options.logPath);
|
|
25818
25997
|
return await new Promise((resolve, reject) => {
|
|
25819
|
-
const commandProcess =
|
|
25820
|
-
|
|
25998
|
+
const commandProcess = $spawnLoggedBashScript({
|
|
25999
|
+
scriptPath,
|
|
26000
|
+
logPath: options.logPath,
|
|
25821
26001
|
});
|
|
25822
26002
|
let stdoutBuffer = '';
|
|
25823
26003
|
let stderrBuffer = '';
|
|
25824
26004
|
let fullOutput = '';
|
|
25825
26005
|
let markerSeen = false;
|
|
26006
|
+
let isCompletedAfterIdleTimeout = false;
|
|
25826
26007
|
let idleTimer;
|
|
25827
26008
|
let settled = false;
|
|
25828
26009
|
let isSettling = false;
|
|
@@ -25864,15 +26045,16 @@
|
|
|
25864
26045
|
});
|
|
25865
26046
|
};
|
|
25866
26047
|
/**
|
|
25867
|
-
*
|
|
26048
|
+
* Stops a marker-completed process tree after its trailing output becomes idle.
|
|
25868
26049
|
*/
|
|
25869
26050
|
const finishAfterIdleTimeout = () => {
|
|
25870
|
-
|
|
26051
|
+
isCompletedAfterIdleTimeout = true;
|
|
26052
|
+
idleTimer = undefined;
|
|
25871
26053
|
try {
|
|
25872
|
-
commandProcess
|
|
26054
|
+
$terminateLoggedBashProcessTree(commandProcess);
|
|
25873
26055
|
}
|
|
25874
26056
|
catch (_a) {
|
|
25875
|
-
//
|
|
26057
|
+
// The close handler below still settles normally when Bash already exited before the idle timer fired.
|
|
25876
26058
|
}
|
|
25877
26059
|
};
|
|
25878
26060
|
/**
|
|
@@ -25931,7 +26113,11 @@
|
|
|
25931
26113
|
const failure = code === 0 || markerSeen
|
|
25932
26114
|
? undefined
|
|
25933
26115
|
: new Error(buildCommandFailureMessage(scriptPathPosix, code, fullOutput));
|
|
25934
|
-
const status =
|
|
26116
|
+
const status = isCompletedAfterIdleTimeout
|
|
26117
|
+
? 'completed after idle timeout'
|
|
26118
|
+
: failure
|
|
26119
|
+
? `failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`
|
|
26120
|
+
: 'succeeded';
|
|
25935
26121
|
settleWithLog(status, () => {
|
|
25936
26122
|
if (!failure) {
|
|
25937
26123
|
resolve(fullOutput);
|
|
@@ -25940,8 +26126,9 @@
|
|
|
25940
26126
|
reject(failure);
|
|
25941
26127
|
});
|
|
25942
26128
|
};
|
|
26129
|
+
// Wait for `close`, not only `exit`, because the Bash wrapper can still be flushing its tee process
|
|
26130
|
+
// substitutions after the direct shell exits.
|
|
25943
26131
|
commandProcess.on('close', handleExit);
|
|
25944
|
-
commandProcess.on('exit', handleExit);
|
|
25945
26132
|
commandProcess.on('disconnect', () => {
|
|
25946
26133
|
const failure = new Error(buildCommandFailureMessage(scriptPathPosix, null, fullOutput));
|
|
25947
26134
|
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
@@ -36811,7 +36998,8 @@
|
|
|
36811
36998
|
requirements = await importReferencedFiles(requirements);
|
|
36812
36999
|
requirements = appendMcpServers(requirements, agentSource);
|
|
36813
37000
|
requirements = appendNonCommitmentContent(requirements, parseResult);
|
|
36814
|
-
|
|
37001
|
+
requirements = appendExampleInteractions(requirements, parseResult);
|
|
37002
|
+
return appendUnknownCommitmentContent(requirements, parseResult);
|
|
36815
37003
|
}
|
|
36816
37004
|
/**
|
|
36817
37005
|
* Imports text files referenced by IMPORT commitments and appends their transformed content to the system message.
|
|
@@ -36933,6 +37121,36 @@
|
|
|
36933
37121
|
}
|
|
36934
37122
|
return appendSystemMessageSection(requirements, nonCommitmentContent);
|
|
36935
37123
|
}
|
|
37124
|
+
/**
|
|
37125
|
+
* Appends unknown commitment blocks as final extra context without applying commitment side effects.
|
|
37126
|
+
*
|
|
37127
|
+
* @param requirements - Current requirements snapshot.
|
|
37128
|
+
* @param parseResult - Parsed source including unknown commitment blocks.
|
|
37129
|
+
* @returns Requirements with unknown commitment context appended at the end of the system message.
|
|
37130
|
+
*
|
|
37131
|
+
* @private internal utility of `augmentAgentModelRequirementsFromSource`
|
|
37132
|
+
*/
|
|
37133
|
+
function appendUnknownCommitmentContent(requirements, parseResult) {
|
|
37134
|
+
const unknownCommitmentContent = getUnknownCommitmentContent(parseResult);
|
|
37135
|
+
if (!unknownCommitmentContent) {
|
|
37136
|
+
return requirements;
|
|
37137
|
+
}
|
|
37138
|
+
return appendSystemMessageSection(requirements, unknownCommitmentContent);
|
|
37139
|
+
}
|
|
37140
|
+
/**
|
|
37141
|
+
* Joins unknown commitment blocks into their final extra-context representation.
|
|
37142
|
+
*
|
|
37143
|
+
* @param parseResult - Parsed source including unknown commitment blocks.
|
|
37144
|
+
* @returns Unknown commitment source blocks in their original order.
|
|
37145
|
+
*
|
|
37146
|
+
* @private internal utility of `appendUnknownCommitmentContent`
|
|
37147
|
+
*/
|
|
37148
|
+
function getUnknownCommitmentContent(parseResult) {
|
|
37149
|
+
return parseResult.unknownCommitments
|
|
37150
|
+
.map((commitment) => commitment.source)
|
|
37151
|
+
.filter(Boolean)
|
|
37152
|
+
.join('\n\n');
|
|
37153
|
+
}
|
|
36936
37154
|
/**
|
|
36937
37155
|
* Collects plain-text lines that were not parsed as commitments and should still become part of the final system message.
|
|
36938
37156
|
*
|
|
@@ -39673,24 +39891,12 @@
|
|
|
39673
39891
|
- @@@
|
|
39674
39892
|
- Keep in mind the DRY _(don't repeat yourself)_ principle.
|
|
39675
39893
|
- Do a proper analysis of the current functionality before you start implementing.
|
|
39676
|
-
- Add the changes into the [changelog](
|
|
39894
|
+
- Add the changes into the [changelog](CHANGELOG.md)
|
|
39895
|
+
- Update the [README](README.md) if needed.
|
|
39896
|
+
- Update the [AGENTS.md](AGENTS.md) for the next job to be done if it makes sense.
|
|
39677
39897
|
`),
|
|
39678
39898
|
isDefaultProjectTemplate: true,
|
|
39679
39899
|
},
|
|
39680
|
-
{
|
|
39681
|
-
id: 'agents-server',
|
|
39682
|
-
relativeFilePath: path.join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'agents-server.md'),
|
|
39683
|
-
slugPrefix: 'agents-server',
|
|
39684
|
-
content: _spaceTrim.spaceTrim(`
|
|
39685
|
-
- @@@
|
|
39686
|
-
- Keep in mind the DRY _(don't repeat yourself)_ principle.
|
|
39687
|
-
- Do a proper analysis of the current functionality before you start implementing.
|
|
39688
|
-
- You are working with the [Agents Server](apps/agents-server)
|
|
39689
|
-
- If you need to do the database migration, do it
|
|
39690
|
-
- Add the changes into the [changelog](changelog/_current-preversion.md)
|
|
39691
|
-
`),
|
|
39692
|
-
isDefaultProjectTemplate: false,
|
|
39693
|
-
},
|
|
39694
39900
|
];
|
|
39695
39901
|
/**
|
|
39696
39902
|
* Project-agnostic coder templates that `ptbk coder init` should materialize in any repository.
|
|
@@ -40782,6 +40988,10 @@
|
|
|
40782
40988
|
console.info(colors__default["default"].gray(`✔ ${definition.label} ${installedVersion} is up to date.`));
|
|
40783
40989
|
return;
|
|
40784
40990
|
}
|
|
40991
|
+
if (installationState === 'installed') {
|
|
40992
|
+
console.info(colors__default["default"].gray(`✔ ${definition.label} ${installedVersion} is installed. Skipped checking for updates.`));
|
|
40993
|
+
return;
|
|
40994
|
+
}
|
|
40785
40995
|
if (installationState === 'unknown') {
|
|
40786
40996
|
console.info(colors__default["default"].gray(`✔ ${definition.label} ${installedVersion} is installed, the newest version could not be checked.`));
|
|
40787
40997
|
return;
|
|
@@ -40995,20 +41205,20 @@
|
|
|
40995
41205
|
// 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`
|
|
40996
41206
|
|
|
40997
41207
|
/**
|
|
40998
|
-
* Detects whether one CLI coding harness is installed globally and whether it is up to date.
|
|
41208
|
+
* Detects whether one CLI coding harness is installed globally and, when enabled, whether it is up to date.
|
|
40999
41209
|
*
|
|
41000
|
-
* Note: `$` is used to indicate that this function is not a pure function - it runs the harness command and
|
|
41210
|
+
* Note: `$` is used to indicate that this function is not a pure function - it runs the harness command and may query npm
|
|
41001
41211
|
*
|
|
41002
41212
|
* @private internal utility of `promptbookCli`
|
|
41003
41213
|
*/
|
|
41004
|
-
async function $checkHarnessInstallation(definition) {
|
|
41214
|
+
async function $checkHarnessInstallation(definition, isHarnessUpdateCheckEnabled = true) {
|
|
41005
41215
|
const [installedVersion, latestVersion] = await Promise.all([
|
|
41006
41216
|
$resolveInstalledHarnessVersion(definition),
|
|
41007
|
-
$resolveLatestNpmPackageVersion(definition.npmPackageName),
|
|
41217
|
+
isHarnessUpdateCheckEnabled ? $resolveLatestNpmPackageVersion(definition.npmPackageName) : Promise.resolve(null),
|
|
41008
41218
|
]);
|
|
41009
41219
|
return {
|
|
41010
41220
|
definition,
|
|
41011
|
-
installationState: resolveHarnessInstallationState(installedVersion, latestVersion),
|
|
41221
|
+
installationState: resolveHarnessInstallationState(installedVersion, latestVersion, isHarnessUpdateCheckEnabled),
|
|
41012
41222
|
installedVersion,
|
|
41013
41223
|
latestVersion,
|
|
41014
41224
|
};
|
|
@@ -41016,10 +41226,13 @@
|
|
|
41016
41226
|
/**
|
|
41017
41227
|
* Derives the installation state from the detected versions.
|
|
41018
41228
|
*/
|
|
41019
|
-
function resolveHarnessInstallationState(installedVersion, latestVersion) {
|
|
41229
|
+
function resolveHarnessInstallationState(installedVersion, latestVersion, isHarnessUpdateCheckEnabled) {
|
|
41020
41230
|
if (installedVersion === null) {
|
|
41021
41231
|
return 'not-installed';
|
|
41022
41232
|
}
|
|
41233
|
+
if (!isHarnessUpdateCheckEnabled) {
|
|
41234
|
+
return 'installed';
|
|
41235
|
+
}
|
|
41023
41236
|
if (latestVersion === null) {
|
|
41024
41237
|
return 'unknown';
|
|
41025
41238
|
}
|
|
@@ -41030,8 +41243,8 @@
|
|
|
41030
41243
|
// Note: [🟡] Code for CLI harness installation check [$checkHarnessInstallation](src/cli/cli-commands/common/harness/$checkHarnessInstallation.ts) should never be published outside of `@promptbook/cli`
|
|
41031
41244
|
|
|
41032
41245
|
/**
|
|
41033
|
-
* Checks that every given CLI coding harness is installed globally and up to date
|
|
41034
|
-
* install
|
|
41246
|
+
* Checks that every given CLI coding harness is installed globally and, when enabled, up to date.
|
|
41247
|
+
* Offers to install missing harnesses and update outdated ones.
|
|
41035
41248
|
*
|
|
41036
41249
|
* Harness names which are `undefined`, for example when no `--harness` is selected in a dry run,
|
|
41037
41250
|
* are ignored so that every call site can pass its raw selection.
|
|
@@ -41040,13 +41253,13 @@
|
|
|
41040
41253
|
*
|
|
41041
41254
|
* @private internal utility of `promptbookCli`
|
|
41042
41255
|
*/
|
|
41043
|
-
async function $ensureHarnessInstallations(harnessNames) {
|
|
41256
|
+
async function $ensureHarnessInstallations(harnessNames, isHarnessUpdateCheckEnabled = true) {
|
|
41044
41257
|
const definitions = resolveCheckedHarnessDefinitions(harnessNames);
|
|
41045
41258
|
if (definitions.length === 0) {
|
|
41046
41259
|
return;
|
|
41047
41260
|
}
|
|
41048
41261
|
// Note: Detection of all harnesses runs in parallel, the questions have to be asked one by one
|
|
41049
|
-
const statuses = await Promise.all(definitions.map((definition) => $checkHarnessInstallation(definition)));
|
|
41262
|
+
const statuses = await Promise.all(definitions.map((definition) => $checkHarnessInstallation(definition, isHarnessUpdateCheckEnabled)));
|
|
41050
41263
|
for (const status of statuses) {
|
|
41051
41264
|
await $applyHarnessInstallationStatus(status);
|
|
41052
41265
|
}
|
|
@@ -41060,6 +41273,27 @@
|
|
|
41060
41273
|
}
|
|
41061
41274
|
// Note: [🟡] Code for CLI harness installation orchestration [$ensureHarnessInstallations](src/cli/cli-commands/common/harness/$ensureHarnessInstallations.ts) should never be published outside of `@promptbook/cli`
|
|
41062
41275
|
|
|
41276
|
+
/**
|
|
41277
|
+
* Registers the shared `--no-harness-update` option on a `ptbk coder` command that uses a coding harness.
|
|
41278
|
+
*
|
|
41279
|
+
* @private internal utility of `promptbookCli`
|
|
41280
|
+
*/
|
|
41281
|
+
function addHarnessUpdateOption(command) {
|
|
41282
|
+
command.option('--no-harness-update', 'Skip checking whether globally installed coding harnesses are up to date');
|
|
41283
|
+
}
|
|
41284
|
+
/**
|
|
41285
|
+
* Converts the Commander harness-update flag into the normalized harness-check option.
|
|
41286
|
+
*
|
|
41287
|
+
* @private internal utility of `promptbookCli`
|
|
41288
|
+
*/
|
|
41289
|
+
function normalizeHarnessUpdateCliOptions(cliOptions) {
|
|
41290
|
+
return {
|
|
41291
|
+
isHarnessUpdateCheckEnabled: cliOptions.harnessUpdate,
|
|
41292
|
+
};
|
|
41293
|
+
}
|
|
41294
|
+
// Note: [🟡] Code for CLI harness update options [harnessUpdateCliOptions](src/cli/cli-commands/common/harnessUpdateCliOptions.ts) should never be published outside of `@promptbook/cli`
|
|
41295
|
+
// Note: [💞] Ignore a discrepancy between file name and exported helper names
|
|
41296
|
+
|
|
41063
41297
|
/**
|
|
41064
41298
|
* Relative path to the Promptbook Coder quick-reference file initialized in project roots.
|
|
41065
41299
|
*
|
|
@@ -41622,14 +41856,16 @@
|
|
|
41622
41856
|
- CODING_AGENT_GIT_EMAIL
|
|
41623
41857
|
- CODING_AGENT_GIT_SIGNING_KEY
|
|
41624
41858
|
|
|
41625
|
-
Checks that the coding harnesses are installed globally and up to date:
|
|
41859
|
+
Checks that the coding harnesses are installed globally and up to date unless \`--no-harness-update\` is used:
|
|
41626
41860
|
${block(listCheckedHarnessLabels())}
|
|
41627
41861
|
|
|
41628
41862
|
${block(CODER_GIT_SYNC_DESCRIPTION)}
|
|
41629
41863
|
`));
|
|
41630
41864
|
addCoderGitSyncOptions(command);
|
|
41865
|
+
addHarnessUpdateOption(command);
|
|
41631
41866
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
41632
41867
|
const gitSync = normalizeCoderGitSyncCliOptions(cliOptions);
|
|
41868
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
41633
41869
|
const projectPath = process.cwd();
|
|
41634
41870
|
// Note: Import the git synchronization dynamically to keep the CLI fast for runs without `--commit`
|
|
41635
41871
|
const { $commitCoderChanges, $startCoderGitSync } = await Promise.resolve().then(function () { return coderGitSync; });
|
|
@@ -41642,7 +41878,7 @@
|
|
|
41642
41878
|
commitScope,
|
|
41643
41879
|
commitMessage: 'Initialize Promptbook Coder',
|
|
41644
41880
|
});
|
|
41645
|
-
await $ensureHarnessInstallations(CODER_INIT_CHECKED_HARNESS_NAMES);
|
|
41881
|
+
await $ensureHarnessInstallations(CODER_INIT_CHECKED_HARNESS_NAMES, isHarnessUpdateCheckEnabled);
|
|
41646
41882
|
}));
|
|
41647
41883
|
}
|
|
41648
41884
|
/**
|
|
@@ -41681,13 +41917,16 @@
|
|
|
41681
41917
|
- Reports the answer of the harness, the response time and the reported usage
|
|
41682
41918
|
- Starts the hourly/weekly quota window before you need it, so it is already refreshing when you do
|
|
41683
41919
|
- Leaves the project exactly as it was — nothing is read, written, changed or committed
|
|
41920
|
+
- Checks that the selected harness is installed globally and up to date unless --no-harness-update is used
|
|
41684
41921
|
- Use --no-ui to stream the raw harness output instead of only the compact result
|
|
41685
41922
|
`));
|
|
41686
41923
|
addPromptRunnerSelectionOptions(command);
|
|
41924
|
+
addHarnessUpdateOption(command);
|
|
41687
41925
|
addPromptRunnerRuntimeOptions(command);
|
|
41688
41926
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
41689
41927
|
const runnerOptions = normalizePromptRunnerSelectionCliOptions(cliOptions, { isAgentRequired: true });
|
|
41690
|
-
|
|
41928
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
41929
|
+
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
41691
41930
|
// Note: Import the ping dynamically to avoid loading heavy dependencies until needed
|
|
41692
41931
|
const { pingCoderHarness } = await Promise.resolve().then(function () { return pingCoderHarness$1; });
|
|
41693
41932
|
const { printCoderPingResult } = await Promise.resolve().then(function () { return printCoderPingResult$1; });
|
|
@@ -42178,7 +42417,7 @@
|
|
|
42178
42417
|
- Optional --isolate runs every prompt in its own temporary git worktree and merges it back when verified
|
|
42179
42418
|
- Optional --preserve-logs keeps temp prompt/log artifacts after successful rounds
|
|
42180
42419
|
- Optional --no-ui keeps plain streaming console output for logging and debugging
|
|
42181
|
-
- Checks that the selected harness is installed globally and up to date before the first prompt
|
|
42420
|
+
- Checks that the selected harness is installed globally and up to date before the first prompt unless --no-harness-update is used
|
|
42182
42421
|
- In interactive mode, checks local and global Promptbook CLI installations and offers to update them
|
|
42183
42422
|
- Supports GPG signing of commits
|
|
42184
42423
|
- Optional pre-coding test run that can stop or repair pre-existing failures
|
|
@@ -42188,6 +42427,7 @@
|
|
|
42188
42427
|
`));
|
|
42189
42428
|
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
42190
42429
|
addPromptRunnerSelectionOptions(command);
|
|
42430
|
+
addHarnessUpdateOption(command);
|
|
42191
42431
|
command.option('--agent <agent-book-path>', 'Path to a .book file whose compiled system message is prepended to each coding prompt');
|
|
42192
42432
|
command.option('--context <context-or-file>', 'Append extra instructions either inline or from a file path relative to the current project');
|
|
42193
42433
|
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
@@ -42229,6 +42469,7 @@
|
|
|
42229
42469
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
42230
42470
|
isAgentRequired: !dryRun,
|
|
42231
42471
|
});
|
|
42472
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
42232
42473
|
// [1] Parse the wait options and --no-auto:
|
|
42233
42474
|
// default: run automatically through the queue (no waiting between prompts)
|
|
42234
42475
|
// --no-auto: wait for user confirmation before each prompt (interactive mode)
|
|
@@ -42239,7 +42480,7 @@
|
|
|
42239
42480
|
if (await $ensurePromptbookCliInstallations()) {
|
|
42240
42481
|
return process.exit(0);
|
|
42241
42482
|
}
|
|
42242
|
-
await $ensureHarnessInstallations([runnerOptions.agentName]);
|
|
42483
|
+
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
42243
42484
|
const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
|
|
42244
42485
|
const waitBetweenPrompts = parseOptionalWaitDuration(waitBetweenPromptsValue, 0);
|
|
42245
42486
|
const waitAfterError = parseOptionalWaitDuration(waitAfterErrorValue, DEFAULT_WAIT_AFTER_ERROR_MS$1);
|
|
@@ -42333,7 +42574,7 @@
|
|
|
42333
42574
|
|
|
42334
42575
|
Features:
|
|
42335
42576
|
- Runs the same prompt processing as \`ptbk coder run\`
|
|
42336
|
-
- Checks that the selected harness is installed globally and up to date on startup
|
|
42577
|
+
- Checks that the selected harness is installed globally and up to date on startup unless --no-harness-update is used
|
|
42337
42578
|
- Does not exit when all prompts are done; polls for new prompt files instead
|
|
42338
42579
|
- Serves a kanban board at http://localhost:<port> for visual progress tracking
|
|
42339
42580
|
- Allows editing prompt files directly from the browser (Trello-style)
|
|
@@ -42345,6 +42586,7 @@
|
|
|
42345
42586
|
.default(DEFAULT_CODER_SERVER_PORT));
|
|
42346
42587
|
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
42347
42588
|
addPromptRunnerSelectionOptions(command);
|
|
42589
|
+
addHarnessUpdateOption(command);
|
|
42348
42590
|
command.option('--agent <agent-book-path>', 'Path to a .book file whose compiled system message is prepended to each coding prompt');
|
|
42349
42591
|
command.option('--context <context-or-file>', 'Append extra instructions either inline or from a file path relative to the current project');
|
|
42350
42592
|
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
@@ -42376,7 +42618,8 @@
|
|
|
42376
42618
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
42377
42619
|
isAgentRequired: !dryRun,
|
|
42378
42620
|
});
|
|
42379
|
-
|
|
42621
|
+
const { isHarnessUpdateCheckEnabled } = normalizeHarnessUpdateCliOptions(cliOptions);
|
|
42622
|
+
await $ensureHarnessInstallations([runnerOptions.agentName], isHarnessUpdateCheckEnabled);
|
|
42380
42623
|
// [1] Parse the wait options and --no-auto (same logic as `coder run`)
|
|
42381
42624
|
const waitForUser = !auto;
|
|
42382
42625
|
const waitAfterPrompt = parseOptionalWaitDuration(waitAfterPromptValue, 0);
|
|
@@ -44300,23 +44543,27 @@
|
|
|
44300
44543
|
// TODO: [🧠][♿] Maybe export through `@promptbook/node`
|
|
44301
44544
|
|
|
44302
44545
|
/**
|
|
44303
|
-
* Attempts to locate the specified application on a Windows system by searching common installation directories.
|
|
44546
|
+
* Attempts to locate the specified application on a Windows system by searching PATH and common installation directories.
|
|
44304
44547
|
* Returns the path to the executable if found, or null otherwise.
|
|
44305
44548
|
*
|
|
44306
44549
|
* @private within the repository
|
|
44307
44550
|
*/
|
|
44308
44551
|
async function locateAppOnWindows({ appName, windowsSuffix, }) {
|
|
44309
44552
|
try {
|
|
44310
|
-
const
|
|
44553
|
+
const EXECUTABLE_FILENAME = windowsSuffix.replace(/^.*[\\/]/, '');
|
|
44554
|
+
const PATH_EXECUTABLE_PATHS = (process.env.PATH || '')
|
|
44555
|
+
.split(path.delimiter)
|
|
44556
|
+
.filter(Boolean)
|
|
44557
|
+
.map((pathPrefix) => path.join(pathPrefix, EXECUTABLE_FILENAME));
|
|
44558
|
+
const INSTALLATION_EXECUTABLE_PATHS = [
|
|
44311
44559
|
process.env.LOCALAPPDATA,
|
|
44312
44560
|
path.join(process.env.LOCALAPPDATA || '', 'Programs'),
|
|
44313
44561
|
process.env.PROGRAMFILES,
|
|
44314
44562
|
process.env['PROGRAMFILES(X86)'],
|
|
44315
|
-
];
|
|
44316
|
-
for (const
|
|
44317
|
-
|
|
44318
|
-
|
|
44319
|
-
return path;
|
|
44563
|
+
].map((pathPrefix) => pathPrefix + windowsSuffix);
|
|
44564
|
+
for (const executablePath of [...PATH_EXECUTABLE_PATHS, ...INSTALLATION_EXECUTABLE_PATHS]) {
|
|
44565
|
+
if (await isExecutable(executablePath, $provideFilesystemForNode())) {
|
|
44566
|
+
return executablePath;
|
|
44320
44567
|
}
|
|
44321
44568
|
}
|
|
44322
44569
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|
|
@@ -75709,6 +75956,10 @@
|
|
|
75709
75956
|
* Constant for prompts dir.
|
|
75710
75957
|
*/
|
|
75711
75958
|
const PROMPTS_DIR$1 = path.join(process.cwd(), 'prompts');
|
|
75959
|
+
/**
|
|
75960
|
+
* Commit message for files changed by a successful or failed pre-coding test in repair mode.
|
|
75961
|
+
*/
|
|
75962
|
+
const PRE_CODING_TEST_CHANGES_COMMIT_MESSAGE = 'test: Apply changes made by pre-coding tests';
|
|
75712
75963
|
/**
|
|
75713
75964
|
* Main entry point for running prompts with the selected agent.
|
|
75714
75965
|
*
|
|
@@ -76032,6 +76283,7 @@
|
|
|
76032
76283
|
});
|
|
76033
76284
|
await ensureWorkingTreeClean();
|
|
76034
76285
|
}
|
|
76286
|
+
const testBeforeCommitScope = await captureTestBeforeCommitScopeIfNeeded(runOptions);
|
|
76035
76287
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
76036
76288
|
const testBeforeResult = await runTestBefore({
|
|
76037
76289
|
testCommand: runOptions.testCommand,
|
|
@@ -76040,6 +76292,11 @@
|
|
|
76040
76292
|
}).finally(() => {
|
|
76041
76293
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
76042
76294
|
});
|
|
76295
|
+
await commitTestBeforeChangesIfNeeded({
|
|
76296
|
+
runOptions,
|
|
76297
|
+
testBeforeCommitScope,
|
|
76298
|
+
waitForRequestedPause,
|
|
76299
|
+
});
|
|
76043
76300
|
if (testBeforeResult.isPassed) {
|
|
76044
76301
|
return hasWaitedForStart;
|
|
76045
76302
|
}
|
|
@@ -76088,6 +76345,38 @@
|
|
|
76088
76345
|
});
|
|
76089
76346
|
return updatedHasWaitedForStart;
|
|
76090
76347
|
}
|
|
76348
|
+
/**
|
|
76349
|
+
* Captures the files present before a `yes-and-fix` pre-coding test, so only changes made by that test can be committed.
|
|
76350
|
+
*/
|
|
76351
|
+
async function captureTestBeforeCommitScopeIfNeeded(runOptions) {
|
|
76352
|
+
if (runOptions.testBefore !== 'yes-and-fix' || runOptions.noCommit) {
|
|
76353
|
+
return undefined;
|
|
76354
|
+
}
|
|
76355
|
+
return captureCoderCommitScope(process.cwd());
|
|
76356
|
+
}
|
|
76357
|
+
/**
|
|
76358
|
+
* Commits files changed by a `yes-and-fix` pre-coding test before the coder continues to a queued or repair prompt.
|
|
76359
|
+
*/
|
|
76360
|
+
async function commitTestBeforeChangesIfNeeded(options) {
|
|
76361
|
+
const { runOptions, testBeforeCommitScope, waitForRequestedPause } = options;
|
|
76362
|
+
if (!testBeforeCommitScope) {
|
|
76363
|
+
return;
|
|
76364
|
+
}
|
|
76365
|
+
const relevantPaths = await resolveCoderCommitScopePaths(testBeforeCommitScope);
|
|
76366
|
+
if (relevantPaths.length === 0) {
|
|
76367
|
+
return;
|
|
76368
|
+
}
|
|
76369
|
+
await waitForRequestedPause({
|
|
76370
|
+
checkpointLabel: 'committing changes made by pre-coding tests',
|
|
76371
|
+
phase: 'verifying',
|
|
76372
|
+
statusMessage: 'Committing changes made by pre-coding tests...',
|
|
76373
|
+
});
|
|
76374
|
+
await commitChanges(PRE_CODING_TEST_CHANGES_COMMIT_MESSAGE, {
|
|
76375
|
+
autoPush: runOptions.autoPush,
|
|
76376
|
+
projectPath: testBeforeCommitScope.projectPath,
|
|
76377
|
+
relevantPaths,
|
|
76378
|
+
});
|
|
76379
|
+
}
|
|
76091
76380
|
/**
|
|
76092
76381
|
* Creates a pause waiter that keeps the progress display and rich UI in sync.
|
|
76093
76382
|
*/
|