@promptbook/cli 0.112.0-43 → 0.112.0-44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/index.es.js +481 -111
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/runGoScript/$runGoScript.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/common/runGoScript/$runGoScriptUntilMarkerIdle.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/common/runGoScript/$runGoScriptWithOutput.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/common/runGoScript/PromptRoundArtifacts.d.ts +35 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/buildScriptLogPath.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/runBashScriptWithOutput.d.ts +5 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +28 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/withPromptRuntimeLog.d.ts +5 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/withTempScript.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -0
- package/esm/src/book-2.0/agent-source/AgentBasicInformation.d.ts +2 -1
- package/esm/src/book-2.0/agent-source/TeammateProfileResolver.d.ts +2 -1
- package/esm/src/commitments/PERSONA/PERSONA.d.ts +7 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +480 -110
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/runGoScript/$runGoScript.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/common/runGoScript/$runGoScriptUntilMarkerIdle.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/common/runGoScript/$runGoScriptWithOutput.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/common/runGoScript/PromptRoundArtifacts.d.ts +35 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/buildScriptLogPath.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/runBashScriptWithOutput.d.ts +5 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +28 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/withPromptRuntimeLog.d.ts +5 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/withTempScript.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -0
- package/umd/src/book-2.0/agent-source/AgentBasicInformation.d.ts +2 -1
- package/umd/src/book-2.0/agent-source/TeammateProfileResolver.d.ts +2 -1
- package/umd/src/commitments/PERSONA/PERSONA.d.ts +7 -0
- package/umd/src/version.d.ts +1 -1
package/umd/index.umd.js
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
* @generated
|
|
61
61
|
* @see https://github.com/webgptorg/promptbook
|
|
62
62
|
*/
|
|
63
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
63
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-44';
|
|
64
64
|
/**
|
|
65
65
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
66
66
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -3027,12 +3027,13 @@
|
|
|
3027
3027
|
command.option('--no-wait', 'Skip user prompts between processing');
|
|
3028
3028
|
command.option('--ignore-git-changes', 'Skip clean working tree check before running prompts', false);
|
|
3029
3029
|
command.option('--allow-credits', 'Allow OpenAI Codex runner to spend credits when rate limits are exhausted', false);
|
|
3030
|
+
command.option('--preserve-logs', 'Keep generated runner shells and runtime logs after successful prompt rounds; failures keep them automatically', false);
|
|
3030
3031
|
command.option('--no-normalize-line-endings', 'Disable automatic LF normalization for files changed in each coding round');
|
|
3031
3032
|
command.option('--auto-push', 'Automatically git push after each commit', false);
|
|
3032
3033
|
command.option('--auto-migrate', 'Run testing-server database migrations automatically after each successfully processed prompt');
|
|
3033
3034
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
3034
3035
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
3035
|
-
const { dryRun, agent, model, context, test, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits, normalizeLineEndings, autoMigrate, allowDestructiveAutoMigrate, autoPush, } = cliOptions;
|
|
3036
|
+
const { dryRun, agent, model, context, test, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits, preserveLogs, normalizeLineEndings, autoMigrate, allowDestructiveAutoMigrate, autoPush, } = cliOptions;
|
|
3036
3037
|
const testCommand = normalizeCommandOptionValue(test);
|
|
3037
3038
|
// Validate agent
|
|
3038
3039
|
let agentName = undefined;
|
|
@@ -3067,6 +3068,7 @@
|
|
|
3067
3068
|
priority,
|
|
3068
3069
|
normalizeLineEndings,
|
|
3069
3070
|
allowCredits,
|
|
3071
|
+
preserveLogs,
|
|
3070
3072
|
autoMigrate,
|
|
3071
3073
|
allowDestructiveAutoMigrate,
|
|
3072
3074
|
autoPush,
|
|
@@ -18951,7 +18953,7 @@
|
|
|
18951
18953
|
* Short one-line description of GOAL.
|
|
18952
18954
|
*/
|
|
18953
18955
|
get description() {
|
|
18954
|
-
return 'Define
|
|
18956
|
+
return 'Define the effective agent **goal**; when multiple goals exist, only the last one stays effective.';
|
|
18955
18957
|
}
|
|
18956
18958
|
/**
|
|
18957
18959
|
* Icon for this commitment.
|
|
@@ -18966,12 +18968,14 @@
|
|
|
18966
18968
|
return _spaceTrim.spaceTrim(`
|
|
18967
18969
|
# ${this.type}
|
|
18968
18970
|
|
|
18969
|
-
Defines the main goal which should be achieved by the AI assistant.
|
|
18971
|
+
Defines the main goal which should be achieved by the AI assistant.
|
|
18972
|
+
There can be multiple goals in source, but after inheritance/source rewriting only the last \`GOAL\` /\`GOALS\` remains effective.
|
|
18970
18973
|
|
|
18971
18974
|
## Key aspects
|
|
18972
18975
|
|
|
18973
18976
|
- Both terms work identically and can be used interchangeably.
|
|
18974
|
-
- Later goals
|
|
18977
|
+
- Later goals overwrite earlier goals.
|
|
18978
|
+
- The public agent profile text is derived from the last goal.
|
|
18975
18979
|
- Goals provide clear direction and purpose for the agent's responses.
|
|
18976
18980
|
- Goals influence decision-making and response prioritization.
|
|
18977
18981
|
|
|
@@ -18984,9 +18988,7 @@
|
|
|
18984
18988
|
\`\`\`book
|
|
18985
18989
|
Customer Support Agent
|
|
18986
18990
|
|
|
18987
|
-
PERSONA You are a helpful customer support representative
|
|
18988
18991
|
GOAL Resolve customer issues quickly and efficiently
|
|
18989
|
-
GOAL Maintain high customer satisfaction scores
|
|
18990
18992
|
GOAL Always follow company policies and procedures
|
|
18991
18993
|
RULE Be polite and professional at all times
|
|
18992
18994
|
\`\`\`
|
|
@@ -18994,9 +18996,7 @@
|
|
|
18994
18996
|
\`\`\`book
|
|
18995
18997
|
Educational Assistant
|
|
18996
18998
|
|
|
18997
|
-
PERSONA You are an educational assistant specializing in mathematics
|
|
18998
18999
|
GOAL Help students understand mathematical concepts clearly
|
|
18999
|
-
GOAL Encourage critical thinking and problem-solving skills
|
|
19000
19000
|
GOAL Ensure all explanations are age-appropriate and accessible
|
|
19001
19001
|
STYLE Use simple language and provide step-by-step explanations
|
|
19002
19002
|
\`\`\`
|
|
@@ -19004,9 +19004,7 @@
|
|
|
19004
19004
|
\`\`\`book
|
|
19005
19005
|
Safety-First Assistant
|
|
19006
19006
|
|
|
19007
|
-
PERSONA You are a general-purpose AI assistant
|
|
19008
19007
|
GOAL Be helpful and informative in all interactions
|
|
19009
|
-
GOAL Provide accurate and reliable information
|
|
19010
19008
|
GOAL Always prioritize user safety and ethical guidelines
|
|
19011
19009
|
RULE Never provide harmful or dangerous advice
|
|
19012
19010
|
\`\`\`
|
|
@@ -21865,7 +21863,16 @@
|
|
|
21865
21863
|
* Short one-line description of PERSONA.
|
|
21866
21864
|
*/
|
|
21867
21865
|
get description() {
|
|
21868
|
-
return '
|
|
21866
|
+
return 'Deprecated legacy profile commitment. Prefer `GOAL` for agent profile text and inheritance-safe rewrites.';
|
|
21867
|
+
}
|
|
21868
|
+
/**
|
|
21869
|
+
* Optional UI/docs-only deprecation metadata.
|
|
21870
|
+
*/
|
|
21871
|
+
get deprecation() {
|
|
21872
|
+
return {
|
|
21873
|
+
message: 'Use `GOAL` for agent profile text and inheritance-safe rewrites.',
|
|
21874
|
+
replacedBy: ['GOAL'],
|
|
21875
|
+
};
|
|
21869
21876
|
}
|
|
21870
21877
|
/**
|
|
21871
21878
|
* Icon for this commitment.
|
|
@@ -21880,16 +21887,24 @@
|
|
|
21880
21887
|
return _spaceTrim.spaceTrim(`
|
|
21881
21888
|
# ${this.type}
|
|
21882
21889
|
|
|
21883
|
-
|
|
21890
|
+
Deprecated legacy commitment that defines who the agent is, their background, expertise, and personality traits.
|
|
21884
21891
|
|
|
21885
|
-
##
|
|
21892
|
+
## Migration
|
|
21886
21893
|
|
|
21887
|
-
-
|
|
21888
|
-
-
|
|
21889
|
-
-
|
|
21890
|
-
-
|
|
21894
|
+
- Existing \`${this.type}\` books still parse and compile.
|
|
21895
|
+
- New books should prefer \`GOAL\`.
|
|
21896
|
+
- Agent profile rendering now prefers the last \`GOAL\` and only falls back to \`${this.type}\` when no goal exists.
|
|
21897
|
+
- Runtime compilation keeps the legacy multi-\`PERSONA\` merge behavior for backward compatibility.
|
|
21891
21898
|
|
|
21892
|
-
##
|
|
21899
|
+
## Preferred replacement
|
|
21900
|
+
|
|
21901
|
+
\`\`\`book
|
|
21902
|
+
Programming Assistant
|
|
21903
|
+
|
|
21904
|
+
GOAL Help the user solve programming problems with practical TypeScript and React guidance.
|
|
21905
|
+
\`\`\`
|
|
21906
|
+
|
|
21907
|
+
## Legacy compatibility example
|
|
21893
21908
|
|
|
21894
21909
|
\`\`\`book
|
|
21895
21910
|
Programming Assistant
|
|
@@ -22654,7 +22669,7 @@
|
|
|
22654
22669
|
\`\`\`book
|
|
22655
22670
|
Legal Assistant
|
|
22656
22671
|
|
|
22657
|
-
|
|
22672
|
+
GOAL Get expert software-development advice from the teammate when legal discussion needs technical context.
|
|
22658
22673
|
TEAM You can talk with http://localhost:4440/agents/GMw67JN8TXxN7y to discuss the legal aspects.
|
|
22659
22674
|
\`\`\`
|
|
22660
22675
|
`);
|
|
@@ -41400,6 +41415,15 @@
|
|
|
41400
41415
|
* @private internal constant of `createAgentModelRequirementsWithCommitments`
|
|
41401
41416
|
*/
|
|
41402
41417
|
const DELETE_COMMITMENT_TYPES = new Set(['DELETE', 'CANCEL', 'DISCARD', 'REMOVE']);
|
|
41418
|
+
/**
|
|
41419
|
+
* Commitments whose earlier occurrences are overwritten by the last occurrence in source order.
|
|
41420
|
+
*
|
|
41421
|
+
* @private internal constant of `createAgentModelRequirementsWithCommitments`
|
|
41422
|
+
*/
|
|
41423
|
+
const OVERWRITTEN_COMMITMENT_GROUP_BY_TYPE = new Map([
|
|
41424
|
+
['GOAL', 'GOAL'],
|
|
41425
|
+
['GOALS', 'GOAL'],
|
|
41426
|
+
]);
|
|
41403
41427
|
/**
|
|
41404
41428
|
* Regex pattern matching markdown horizontal lines that should not be copied into the final system message.
|
|
41405
41429
|
*
|
|
@@ -41450,7 +41474,7 @@
|
|
|
41450
41474
|
*/
|
|
41451
41475
|
async function createAgentModelRequirementsWithCommitments(agentSource, modelName, options) {
|
|
41452
41476
|
const parseResult = parseAgentSourceWithCommitments(agentSource);
|
|
41453
|
-
const filteredCommitments = filterDeletedCommitments(parseResult.commitments);
|
|
41477
|
+
const filteredCommitments = filterOverwrittenCommitments(filterDeletedCommitments(parseResult.commitments));
|
|
41454
41478
|
let requirements = createInitialAgentModelRequirements(parseResult.agentName, modelName);
|
|
41455
41479
|
requirements = await applyCommitmentsToRequirements(requirements, filteredCommitments, options);
|
|
41456
41480
|
requirements = aggregateUseCommitmentSystemMessages(requirements, filteredCommitments);
|
|
@@ -41461,6 +41485,35 @@
|
|
|
41461
41485
|
requirements = await applyPendingInlineKnowledgeSources(requirements, options === null || options === void 0 ? void 0 : options.inlineKnowledgeSourceUploader);
|
|
41462
41486
|
return finalizeRequirements(requirements);
|
|
41463
41487
|
}
|
|
41488
|
+
/**
|
|
41489
|
+
* Removes earlier commitments that are overwritten by later commitments of the same semantic group.
|
|
41490
|
+
*
|
|
41491
|
+
* This currently keeps only the last `GOAL` / `GOALS` commitment so inheritance rewrites
|
|
41492
|
+
* and multi-goal sources expose one effective goal to the runtime.
|
|
41493
|
+
*
|
|
41494
|
+
* @param commitments - Parsed commitments after DELETE-like filtering.
|
|
41495
|
+
* @returns Commitments with overwritten entries removed while preserving source order.
|
|
41496
|
+
*
|
|
41497
|
+
* @private internal utility of `createAgentModelRequirementsWithCommitments`
|
|
41498
|
+
*/
|
|
41499
|
+
function filterOverwrittenCommitments(commitments) {
|
|
41500
|
+
const seenOverwriteGroups = new Set();
|
|
41501
|
+
const keptCommitments = [];
|
|
41502
|
+
for (let index = commitments.length - 1; index >= 0; index--) {
|
|
41503
|
+
const commitment = commitments[index];
|
|
41504
|
+
const overwriteGroup = OVERWRITTEN_COMMITMENT_GROUP_BY_TYPE.get(commitment.type);
|
|
41505
|
+
if (!overwriteGroup) {
|
|
41506
|
+
keptCommitments.push(commitment);
|
|
41507
|
+
continue;
|
|
41508
|
+
}
|
|
41509
|
+
if (seenOverwriteGroups.has(overwriteGroup)) {
|
|
41510
|
+
continue;
|
|
41511
|
+
}
|
|
41512
|
+
seenOverwriteGroups.add(overwriteGroup);
|
|
41513
|
+
keptCommitments.push(commitment);
|
|
41514
|
+
}
|
|
41515
|
+
return keptCommitments.reverse();
|
|
41516
|
+
}
|
|
41464
41517
|
/**
|
|
41465
41518
|
* Creates the initial requirements object with the parsed agent name stored in metadata and an optional model override.
|
|
41466
41519
|
*
|
|
@@ -42103,7 +42156,7 @@
|
|
|
42103
42156
|
function parseAgentSource(agentSource) {
|
|
42104
42157
|
const parseResult = parseAgentSourceWithCommitments(agentSource);
|
|
42105
42158
|
const resolvedAgentName = parseResult.agentName || createDefaultAgentName(agentSource);
|
|
42106
|
-
const personaDescription =
|
|
42159
|
+
const personaDescription = extractAgentProfileText(parseResult.commitments);
|
|
42107
42160
|
const initialMessage = extractInitialMessage(parseResult.commitments);
|
|
42108
42161
|
const parsedProfile = extractParsedAgentProfile(parseResult.commitments);
|
|
42109
42162
|
ensureMetaFullname(parsedProfile.meta, resolvedAgentName);
|
|
@@ -42207,25 +42260,33 @@
|
|
|
42207
42260
|
*/
|
|
42208
42261
|
const LOCAL_AGENT_REFERENCE_PREFIXES = ['./', '../', '/'];
|
|
42209
42262
|
/**
|
|
42210
|
-
*
|
|
42263
|
+
* Resolves the public agent profile text from the last GOAL/GOALS commitment,
|
|
42264
|
+
* falling back to the deprecated PERSONA/PERSONAE commitments when no goal exists.
|
|
42211
42265
|
*
|
|
42212
42266
|
* @private internal utility of `parseAgentSource`
|
|
42213
42267
|
*/
|
|
42214
|
-
function
|
|
42215
|
-
let
|
|
42268
|
+
function extractAgentProfileText(commitments) {
|
|
42269
|
+
let goalDescription = '';
|
|
42270
|
+
let hasGoalDescription = false;
|
|
42271
|
+
let personaDescription = '';
|
|
42272
|
+
let hasPersonaDescription = false;
|
|
42216
42273
|
for (const commitment of commitments) {
|
|
42217
|
-
if (commitment.type
|
|
42218
|
-
|
|
42274
|
+
if (commitment.type === 'GOAL' || commitment.type === 'GOALS') {
|
|
42275
|
+
goalDescription = commitment.content;
|
|
42276
|
+
hasGoalDescription = true;
|
|
42219
42277
|
}
|
|
42220
|
-
if (
|
|
42221
|
-
personaDescription =
|
|
42278
|
+
if (commitment.type === 'PERSONA' || commitment.type === 'PERSONAE') {
|
|
42279
|
+
personaDescription = commitment.content;
|
|
42280
|
+
hasPersonaDescription = true;
|
|
42222
42281
|
}
|
|
42223
|
-
else {
|
|
42224
|
-
personaDescription += `\n\n${personaDescription}`;
|
|
42225
|
-
}
|
|
42226
|
-
personaDescription += commitment.content;
|
|
42227
42282
|
}
|
|
42228
|
-
|
|
42283
|
+
if (hasGoalDescription) {
|
|
42284
|
+
return goalDescription;
|
|
42285
|
+
}
|
|
42286
|
+
if (hasPersonaDescription) {
|
|
42287
|
+
return personaDescription;
|
|
42288
|
+
}
|
|
42289
|
+
return null;
|
|
42229
42290
|
}
|
|
42230
42291
|
/**
|
|
42231
42292
|
* Resolves the last INITIAL MESSAGE commitment, which is the public initial-message value.
|
|
@@ -42712,7 +42773,7 @@
|
|
|
42712
42773
|
* Selects the best model using the preparePersona function
|
|
42713
42774
|
* This directly uses preparePersona to ensure DRY principle
|
|
42714
42775
|
*
|
|
42715
|
-
* @param agentSource The agent source to derive
|
|
42776
|
+
* @param agentSource The agent source to derive effective profile text from
|
|
42716
42777
|
* @param llmTools LLM tools for preparing persona
|
|
42717
42778
|
* @returns The name of the best selected model
|
|
42718
42779
|
*
|
|
@@ -42720,9 +42781,9 @@
|
|
|
42720
42781
|
*/
|
|
42721
42782
|
async function selectBestModelUsingPersona(agentSource, llmTools) {
|
|
42722
42783
|
var _a;
|
|
42723
|
-
// Parse agent source to get
|
|
42784
|
+
// Parse agent source to get the effective profile description
|
|
42724
42785
|
const { agentName, personaDescription } = parseAgentSource(agentSource);
|
|
42725
|
-
// Use agent name as fallback if no
|
|
42786
|
+
// Use agent name as fallback if no profile description is available
|
|
42726
42787
|
const description = personaDescription || agentName || 'AI Agent';
|
|
42727
42788
|
try {
|
|
42728
42789
|
// Use preparePersona directly
|
|
@@ -44184,7 +44245,7 @@
|
|
|
44184
44245
|
/**
|
|
44185
44246
|
* CLI usage text for this script.
|
|
44186
44247
|
*/
|
|
44187
|
-
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--agent <agent-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--allow-credits] [--auto-migrate] [--allow-destructive-auto-migrate] [--no-wait] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push]';
|
|
44248
|
+
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--agent <agent-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--allow-credits] [--preserve-logs] [--auto-migrate] [--allow-destructive-auto-migrate] [--no-wait] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push]';
|
|
44188
44249
|
/**
|
|
44189
44250
|
* Top-level flags supported by this command.
|
|
44190
44251
|
*/
|
|
@@ -44197,6 +44258,7 @@
|
|
|
44197
44258
|
'--thinking-level',
|
|
44198
44259
|
'--priority',
|
|
44199
44260
|
'--allow-credits',
|
|
44261
|
+
'--preserve-logs',
|
|
44200
44262
|
'--auto-migrate',
|
|
44201
44263
|
'--allow-destructive-auto-migrate',
|
|
44202
44264
|
'--no-wait',
|
|
@@ -44233,6 +44295,7 @@
|
|
|
44233
44295
|
const ignoreGitChanges = args.includes('--ignore-git-changes');
|
|
44234
44296
|
const normalizeLineEndings = !args.includes('--no-normalize-line-endings');
|
|
44235
44297
|
const allowCredits = args.includes('--allow-credits');
|
|
44298
|
+
const preserveLogs = args.includes('--preserve-logs');
|
|
44236
44299
|
const autoMigrate = args.includes('--auto-migrate');
|
|
44237
44300
|
const allowDestructiveAutoMigrate = args.includes('--allow-destructive-auto-migrate');
|
|
44238
44301
|
const autoPush = args.includes('--auto-push');
|
|
@@ -44258,6 +44321,7 @@
|
|
|
44258
44321
|
ignoreGitChanges,
|
|
44259
44322
|
normalizeLineEndings,
|
|
44260
44323
|
allowCredits,
|
|
44324
|
+
preserveLogs,
|
|
44261
44325
|
autoMigrate,
|
|
44262
44326
|
allowDestructiveAutoMigrate,
|
|
44263
44327
|
autoPush,
|
|
@@ -44751,6 +44815,91 @@
|
|
|
44751
44815
|
return promises.readFile(contextPath, 'utf-8');
|
|
44752
44816
|
}
|
|
44753
44817
|
|
|
44818
|
+
/**
|
|
44819
|
+
* Builds the temporary live runtime log path for one prompt script and its sibling test script.
|
|
44820
|
+
*/
|
|
44821
|
+
function buildScriptLogPath(scriptPath) {
|
|
44822
|
+
const basePath = scriptPath.replace(/\.test\.sh$/iu, '').replace(/\.sh$/iu, '');
|
|
44823
|
+
return `${basePath}.log.txt`;
|
|
44824
|
+
}
|
|
44825
|
+
|
|
44826
|
+
/**
|
|
44827
|
+
* Runs one prompt-processing round with a dedicated temporary runtime log file and optionally defers cleanup to the round tracker.
|
|
44828
|
+
*/
|
|
44829
|
+
async function withPromptRuntimeLog(scriptPath, handler, promptRoundArtifacts) {
|
|
44830
|
+
const logPath = buildScriptLogPath(scriptPath);
|
|
44831
|
+
await promises.unlink(logPath).catch(() => undefined);
|
|
44832
|
+
promptRoundArtifacts === null || promptRoundArtifacts === void 0 ? void 0 : promptRoundArtifacts.track(logPath, 'runtime-log');
|
|
44833
|
+
try {
|
|
44834
|
+
return await handler(logPath);
|
|
44835
|
+
}
|
|
44836
|
+
finally {
|
|
44837
|
+
if (!promptRoundArtifacts) {
|
|
44838
|
+
await promises.unlink(logPath).catch(() => undefined);
|
|
44839
|
+
}
|
|
44840
|
+
}
|
|
44841
|
+
}
|
|
44842
|
+
|
|
44843
|
+
/**
|
|
44844
|
+
* Shared artifact kinds preserved for debugging when a prompt round fails.
|
|
44845
|
+
*/
|
|
44846
|
+
const FAILURE_PRESERVED_ARTIFACT_KINDS = new Set(['runner-script', 'runtime-log']);
|
|
44847
|
+
/**
|
|
44848
|
+
* Shared artifact kinds preserved after a successful prompt round when explicitly requested.
|
|
44849
|
+
*/
|
|
44850
|
+
const SUCCESS_PRESERVED_ARTIFACT_KINDS = new Set(['runner-script', 'runtime-log']);
|
|
44851
|
+
/**
|
|
44852
|
+
* Empty preserved-artifact set used for successful rounds without `--preserve-logs`.
|
|
44853
|
+
*/
|
|
44854
|
+
const NO_PRESERVED_ARTIFACT_KINDS = new Set();
|
|
44855
|
+
/**
|
|
44856
|
+
* Tracks temporary prompt-round artifacts and deletes only those not preserved for the final round outcome.
|
|
44857
|
+
*/
|
|
44858
|
+
class PromptRoundArtifacts {
|
|
44859
|
+
/**
|
|
44860
|
+
* Creates a new prompt-round artifact tracker.
|
|
44861
|
+
*/
|
|
44862
|
+
constructor(preservedArtifactKindsByOutcome) {
|
|
44863
|
+
this.preservedArtifactKindsByOutcome = preservedArtifactKindsByOutcome;
|
|
44864
|
+
this.trackedArtifacts = new Map();
|
|
44865
|
+
}
|
|
44866
|
+
/**
|
|
44867
|
+
* Registers one temporary artifact for round-final cleanup.
|
|
44868
|
+
*/
|
|
44869
|
+
track(path, kind) {
|
|
44870
|
+
this.trackedArtifacts.set(path, kind);
|
|
44871
|
+
}
|
|
44872
|
+
/**
|
|
44873
|
+
* Cleans up all tracked artifacts that should not survive the final round outcome.
|
|
44874
|
+
*/
|
|
44875
|
+
async cleanup(outcome) {
|
|
44876
|
+
const preservedArtifactKinds = this.preservedArtifactKindsByOutcome[outcome];
|
|
44877
|
+
const trackedArtifacts = [...this.trackedArtifacts.entries()];
|
|
44878
|
+
this.trackedArtifacts.clear();
|
|
44879
|
+
await Promise.all(trackedArtifacts.map(async ([path, kind]) => {
|
|
44880
|
+
if (preservedArtifactKinds.has(kind)) {
|
|
44881
|
+
return;
|
|
44882
|
+
}
|
|
44883
|
+
await promises.unlink(path).catch(() => undefined);
|
|
44884
|
+
}));
|
|
44885
|
+
}
|
|
44886
|
+
}
|
|
44887
|
+
/**
|
|
44888
|
+
* Creates the default artifact-retention policy used by `ptbk coder run`.
|
|
44889
|
+
*/
|
|
44890
|
+
function createCoderRunPromptRoundArtifacts(isPreserveLogs) {
|
|
44891
|
+
return new PromptRoundArtifacts({
|
|
44892
|
+
success: isPreserveLogs ? SUCCESS_PRESERVED_ARTIFACT_KINDS : NO_PRESERVED_ARTIFACT_KINDS,
|
|
44893
|
+
failure: FAILURE_PRESERVED_ARTIFACT_KINDS,
|
|
44894
|
+
});
|
|
44895
|
+
}
|
|
44896
|
+
/**
|
|
44897
|
+
* Derives the tracked artifact kind from one temporary shell path.
|
|
44898
|
+
*/
|
|
44899
|
+
function getPromptRoundArtifactKindFromScriptPath(scriptPath) {
|
|
44900
|
+
return scriptPath.toLowerCase().endsWith('.test.sh') ? 'test-script' : 'runner-script';
|
|
44901
|
+
}
|
|
44902
|
+
|
|
44754
44903
|
/**
|
|
44755
44904
|
* Waits for the user to press Enter before continuing.
|
|
44756
44905
|
*/
|
|
@@ -47054,25 +47203,186 @@
|
|
|
47054
47203
|
}
|
|
47055
47204
|
|
|
47056
47205
|
/**
|
|
47057
|
-
*
|
|
47206
|
+
* Environment variable read by the shell wrapper to tee live output into the temporary runtime log file.
|
|
47207
|
+
*/
|
|
47208
|
+
const PTBK_CODER_LOG_FILE_ENV_NAME = 'PTBK_CODER_LOG_FILE';
|
|
47209
|
+
/**
|
|
47210
|
+
* Small bash wrapper that preserves stdout/stderr streams while teeing both into the runtime log file.
|
|
47211
|
+
*/
|
|
47212
|
+
const LOGGED_BASH_WRAPPER_COMMAND = `
|
|
47213
|
+
if [ -n "\${${PTBK_CODER_LOG_FILE_ENV_NAME}:-}" ]; then
|
|
47214
|
+
exec > >(tee -a "\$${PTBK_CODER_LOG_FILE_ENV_NAME}") 2> >(tee -a "\$${PTBK_CODER_LOG_FILE_ENV_NAME}" >&2)
|
|
47215
|
+
fi
|
|
47216
|
+
bash "$1"
|
|
47217
|
+
`.trim();
|
|
47218
|
+
/**
|
|
47219
|
+
* Shapes one bash invocation that optionally mirrors live script output into a temporary log file.
|
|
47220
|
+
*/
|
|
47221
|
+
function buildLoggedBashExecution(scriptPath, logPath) {
|
|
47222
|
+
return {
|
|
47223
|
+
args: ['-lc', LOGGED_BASH_WRAPPER_COMMAND, 'ptbk-coder-temp-script', toPosixPath(scriptPath)],
|
|
47224
|
+
env: logPath ? { [PTBK_CODER_LOG_FILE_ENV_NAME]: toPosixPath(logPath) } : undefined,
|
|
47225
|
+
};
|
|
47226
|
+
}
|
|
47227
|
+
/**
|
|
47228
|
+
* Appends one execution-start section with the raw script input before the shell begins producing output.
|
|
47229
|
+
*/
|
|
47230
|
+
async function appendScriptExecutionLogStart({ scriptPath, scriptContent, logPath, }) {
|
|
47231
|
+
if (!logPath) {
|
|
47232
|
+
return;
|
|
47233
|
+
}
|
|
47234
|
+
await promises.mkdir(path.dirname(logPath), { recursive: true });
|
|
47235
|
+
const scriptKind = describeTempScriptKind(scriptPath);
|
|
47236
|
+
const normalizedInput = scriptContent.replace(/\r\n/g, '\n').trimEnd();
|
|
47237
|
+
const logSection = [
|
|
47238
|
+
`=== ${scriptKind} started at ${new Date().toISOString()} ===`,
|
|
47239
|
+
`Script path: ${toPosixPath(scriptPath)}`,
|
|
47240
|
+
'',
|
|
47241
|
+
'--- raw input ---',
|
|
47242
|
+
normalizedInput,
|
|
47243
|
+
'',
|
|
47244
|
+
'--- raw output ---',
|
|
47245
|
+
'',
|
|
47246
|
+
].join('\n');
|
|
47247
|
+
await promises.appendFile(logPath, `${logSection}\n`, 'utf-8');
|
|
47248
|
+
}
|
|
47249
|
+
/**
|
|
47250
|
+
* Appends one execution-finish section after the shell settles.
|
|
47251
|
+
*/
|
|
47252
|
+
async function appendScriptExecutionLogFinish({ scriptPath, logPath, status, details, }) {
|
|
47253
|
+
if (!logPath) {
|
|
47254
|
+
return;
|
|
47255
|
+
}
|
|
47256
|
+
const scriptKind = describeTempScriptKind(scriptPath);
|
|
47257
|
+
const logLines = [
|
|
47258
|
+
'',
|
|
47259
|
+
`=== ${scriptKind} finished at ${new Date().toISOString()} ===`,
|
|
47260
|
+
`Status: ${status}`,
|
|
47261
|
+
];
|
|
47262
|
+
if (details !== undefined) {
|
|
47263
|
+
logLines.push('');
|
|
47264
|
+
logLines.push('--- details ---');
|
|
47265
|
+
logLines.push(formatUnknownErrorDetails(details));
|
|
47266
|
+
}
|
|
47267
|
+
logLines.push('');
|
|
47268
|
+
await promises.appendFile(logPath, `${logLines.join('\n')}\n`, 'utf-8');
|
|
47269
|
+
}
|
|
47270
|
+
/**
|
|
47271
|
+
* Distinguishes prompt-runner and verification temp shells in the shared runtime log.
|
|
47272
|
+
*/
|
|
47273
|
+
function describeTempScriptKind(scriptPath) {
|
|
47274
|
+
return scriptPath.toLowerCase().endsWith('.test.sh') ? 'test shell' : 'runner shell';
|
|
47275
|
+
}
|
|
47276
|
+
|
|
47277
|
+
/**
|
|
47278
|
+
* Runs one temporary bash script, optionally mirroring its raw input/output into a live runtime log file.
|
|
47279
|
+
*/
|
|
47280
|
+
async function runBashScriptWithOutput(options) {
|
|
47281
|
+
await appendScriptExecutionLogStart(options);
|
|
47282
|
+
const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
|
|
47283
|
+
const scriptPathPosix = toPosixPath(options.scriptPath);
|
|
47284
|
+
return await new Promise((resolve, reject) => {
|
|
47285
|
+
const commandProcess = child_process.spawn('bash', bashExecution.args, {
|
|
47286
|
+
env: bashExecution.env ? { ...process.env, ...bashExecution.env } : process.env,
|
|
47287
|
+
});
|
|
47288
|
+
let output = '';
|
|
47289
|
+
let settled = false;
|
|
47290
|
+
let isSettling = false;
|
|
47291
|
+
/**
|
|
47292
|
+
* Appends the final log footer before settling.
|
|
47293
|
+
*/
|
|
47294
|
+
const finishLog = async (status, details) => {
|
|
47295
|
+
await appendScriptExecutionLogFinish({
|
|
47296
|
+
scriptPath: options.scriptPath,
|
|
47297
|
+
logPath: options.logPath,
|
|
47298
|
+
status,
|
|
47299
|
+
details,
|
|
47300
|
+
});
|
|
47301
|
+
};
|
|
47302
|
+
/**
|
|
47303
|
+
* Ensures the promise settles only once.
|
|
47304
|
+
*/
|
|
47305
|
+
const settleOnce = (handler) => {
|
|
47306
|
+
if (settled) {
|
|
47307
|
+
return;
|
|
47308
|
+
}
|
|
47309
|
+
settled = true;
|
|
47310
|
+
handler();
|
|
47311
|
+
};
|
|
47312
|
+
/**
|
|
47313
|
+
* Appends the final log footer and settles the promise exactly once.
|
|
47314
|
+
*/
|
|
47315
|
+
const settleWithLog = (status, handler, details) => {
|
|
47316
|
+
if (isSettling || settled) {
|
|
47317
|
+
return;
|
|
47318
|
+
}
|
|
47319
|
+
isSettling = true;
|
|
47320
|
+
void finishLog(status, details).finally(() => {
|
|
47321
|
+
settleOnce(handler);
|
|
47322
|
+
});
|
|
47323
|
+
};
|
|
47324
|
+
commandProcess.stdout.on('data', (stdout) => {
|
|
47325
|
+
const chunk = stdout.toString();
|
|
47326
|
+
output += chunk;
|
|
47327
|
+
console.info(chunk);
|
|
47328
|
+
});
|
|
47329
|
+
commandProcess.stderr.on('data', (stderr) => {
|
|
47330
|
+
const chunk = stderr.toString();
|
|
47331
|
+
output += chunk;
|
|
47332
|
+
if (chunk.trim()) {
|
|
47333
|
+
console.warn(chunk);
|
|
47334
|
+
}
|
|
47335
|
+
});
|
|
47336
|
+
/**
|
|
47337
|
+
* Handles process exit and resolves or rejects accordingly.
|
|
47338
|
+
*/
|
|
47339
|
+
const handleExit = (code) => {
|
|
47340
|
+
if (code === 0) {
|
|
47341
|
+
settleWithLog('succeeded', () => resolve(_spaceTrim.spaceTrim(output)));
|
|
47342
|
+
return;
|
|
47343
|
+
}
|
|
47344
|
+
const failure = new Error(_spaceTrim.spaceTrim(output) || `Command "bash ${scriptPathPosix}" exited with code ${code}`);
|
|
47345
|
+
settleWithLog(`failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`, () => reject(failure), failure);
|
|
47346
|
+
};
|
|
47347
|
+
commandProcess.on('close', handleExit);
|
|
47348
|
+
commandProcess.on('exit', handleExit);
|
|
47349
|
+
commandProcess.on('disconnect', () => {
|
|
47350
|
+
const failure = new Error(`Command "bash ${scriptPathPosix}" disconnected`);
|
|
47351
|
+
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
47352
|
+
});
|
|
47353
|
+
commandProcess.on('error', (error) => {
|
|
47354
|
+
const failure = new Error(`Command "bash ${scriptPathPosix}" failed: ${error.message}`);
|
|
47355
|
+
settleWithLog('failed before completion', () => reject(failure), failure);
|
|
47356
|
+
});
|
|
47357
|
+
});
|
|
47358
|
+
}
|
|
47359
|
+
|
|
47360
|
+
/**
|
|
47361
|
+
* Creates a temporary script file, runs a handler, and either cleans it up immediately or defers cleanup to the round tracker.
|
|
47058
47362
|
*/
|
|
47059
47363
|
async function withTempScript(options, handler) {
|
|
47060
|
-
const { scriptPath, scriptContent } = options;
|
|
47364
|
+
const { scriptPath, scriptContent, promptRoundArtifacts } = options;
|
|
47061
47365
|
await promises.mkdir(posix.dirname(scriptPath), { recursive: true });
|
|
47062
47366
|
await promises.writeFile(scriptPath, scriptContent, 'utf-8');
|
|
47063
|
-
|
|
47064
|
-
|
|
47065
|
-
|
|
47367
|
+
promptRoundArtifacts === null || promptRoundArtifacts === void 0 ? void 0 : promptRoundArtifacts.track(scriptPath, getPromptRoundArtifactKindFromScriptPath(scriptPath));
|
|
47368
|
+
try {
|
|
47369
|
+
return await handler(scriptPath);
|
|
47370
|
+
}
|
|
47371
|
+
finally {
|
|
47372
|
+
if (!promptRoundArtifacts) {
|
|
47373
|
+
await promises.unlink(scriptPath).catch(() => undefined);
|
|
47374
|
+
}
|
|
47375
|
+
}
|
|
47066
47376
|
}
|
|
47067
47377
|
|
|
47068
47378
|
/**
|
|
47069
|
-
* Creates a temporary script file, runs it, captures output, and
|
|
47379
|
+
* Creates a temporary script file, runs it, captures output, and cleans it up immediately unless a round tracker defers that cleanup.
|
|
47070
47380
|
*/
|
|
47071
47381
|
async function $runGoScriptWithOutput(options) {
|
|
47072
47382
|
return await withTempScript(options, async (scriptPath) => {
|
|
47073
|
-
return await
|
|
47074
|
-
|
|
47075
|
-
|
|
47383
|
+
return await runBashScriptWithOutput({
|
|
47384
|
+
...options,
|
|
47385
|
+
scriptPath,
|
|
47076
47386
|
});
|
|
47077
47387
|
});
|
|
47078
47388
|
}
|
|
@@ -47168,6 +47478,8 @@
|
|
|
47168
47478
|
const output = await $runGoScriptWithOutput({
|
|
47169
47479
|
scriptPath: options.scriptPath,
|
|
47170
47480
|
scriptContent,
|
|
47481
|
+
logPath: options.logPath,
|
|
47482
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
47171
47483
|
});
|
|
47172
47484
|
const usage = parseClaudeCodeJsonOutput(output);
|
|
47173
47485
|
return { usage };
|
|
@@ -47175,13 +47487,13 @@
|
|
|
47175
47487
|
}
|
|
47176
47488
|
|
|
47177
47489
|
/**
|
|
47178
|
-
* Creates a temporary script file, runs it, and
|
|
47490
|
+
* Creates a temporary script file, runs it, and cleans it up immediately unless a round tracker defers that cleanup.
|
|
47179
47491
|
*/
|
|
47180
47492
|
async function $runGoScript(options) {
|
|
47181
47493
|
await withTempScript(options, async (scriptPath) => {
|
|
47182
|
-
await
|
|
47183
|
-
|
|
47184
|
-
|
|
47494
|
+
await runBashScriptWithOutput({
|
|
47495
|
+
...options,
|
|
47496
|
+
scriptPath,
|
|
47185
47497
|
});
|
|
47186
47498
|
});
|
|
47187
47499
|
}
|
|
@@ -47230,6 +47542,8 @@
|
|
|
47230
47542
|
await $runGoScript({
|
|
47231
47543
|
scriptPath: options.scriptPath,
|
|
47232
47544
|
scriptContent,
|
|
47545
|
+
logPath: options.logPath,
|
|
47546
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
47233
47547
|
});
|
|
47234
47548
|
return { usage: UNCERTAIN_USAGE };
|
|
47235
47549
|
}
|
|
@@ -47353,6 +47667,8 @@
|
|
|
47353
47667
|
const output = await $runGoScriptWithOutput({
|
|
47354
47668
|
scriptPath: options.scriptPath,
|
|
47355
47669
|
scriptContent,
|
|
47670
|
+
logPath: options.logPath,
|
|
47671
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
47356
47672
|
});
|
|
47357
47673
|
const usage = parseGeminiUsageFromOutput(output, options.prompt, this.options.model);
|
|
47358
47674
|
return { usage };
|
|
@@ -47408,6 +47724,8 @@
|
|
|
47408
47724
|
await $runGoScript({
|
|
47409
47725
|
scriptPath: options.scriptPath,
|
|
47410
47726
|
scriptContent,
|
|
47727
|
+
logPath: options.logPath,
|
|
47728
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
47411
47729
|
});
|
|
47412
47730
|
return { usage: UNCERTAIN_USAGE };
|
|
47413
47731
|
}
|
|
@@ -47444,14 +47762,30 @@
|
|
|
47444
47762
|
async function runScriptUntilMarkerIdle(options) {
|
|
47445
47763
|
const { scriptPath, completionLineMatcher, idleTimeoutMs } = options;
|
|
47446
47764
|
const scriptPathPosix = toPosixPath(scriptPath);
|
|
47765
|
+
await appendScriptExecutionLogStart(options);
|
|
47766
|
+
const bashExecution = buildLoggedBashExecution(scriptPath, options.logPath);
|
|
47447
47767
|
return await new Promise((resolve, reject) => {
|
|
47448
|
-
const commandProcess = child_process.spawn('bash',
|
|
47768
|
+
const commandProcess = child_process.spawn('bash', bashExecution.args, {
|
|
47769
|
+
env: bashExecution.env ? { ...process.env, ...bashExecution.env } : process.env,
|
|
47770
|
+
});
|
|
47449
47771
|
let stdoutBuffer = '';
|
|
47450
47772
|
let stderrBuffer = '';
|
|
47451
47773
|
let fullOutput = '';
|
|
47452
47774
|
let markerSeen = false;
|
|
47453
47775
|
let idleTimer;
|
|
47454
47776
|
let settled = false;
|
|
47777
|
+
let isSettling = false;
|
|
47778
|
+
/**
|
|
47779
|
+
* Appends the final log footer before settling.
|
|
47780
|
+
*/
|
|
47781
|
+
const finishLog = async (status, details) => {
|
|
47782
|
+
await appendScriptExecutionLogFinish({
|
|
47783
|
+
scriptPath,
|
|
47784
|
+
logPath: options.logPath,
|
|
47785
|
+
status,
|
|
47786
|
+
details,
|
|
47787
|
+
});
|
|
47788
|
+
};
|
|
47455
47789
|
/**
|
|
47456
47790
|
* Ensures the promise settles only once.
|
|
47457
47791
|
*/
|
|
@@ -47466,6 +47800,18 @@
|
|
|
47466
47800
|
}
|
|
47467
47801
|
handler();
|
|
47468
47802
|
};
|
|
47803
|
+
/**
|
|
47804
|
+
* Appends the final log footer and settles the promise exactly once.
|
|
47805
|
+
*/
|
|
47806
|
+
const settleWithLog = (status, handler, details) => {
|
|
47807
|
+
if (isSettling || settled) {
|
|
47808
|
+
return;
|
|
47809
|
+
}
|
|
47810
|
+
isSettling = true;
|
|
47811
|
+
void finishLog(status, details).finally(() => {
|
|
47812
|
+
settleOnce(handler);
|
|
47813
|
+
});
|
|
47814
|
+
};
|
|
47469
47815
|
/**
|
|
47470
47816
|
* Resets the idle timer that triggers termination after inactivity.
|
|
47471
47817
|
*/
|
|
@@ -47475,7 +47821,7 @@
|
|
|
47475
47821
|
}
|
|
47476
47822
|
idleTimer = setTimeout(() => {
|
|
47477
47823
|
commandProcess.kill();
|
|
47478
|
-
|
|
47824
|
+
settleWithLog('completed after idle timeout', () => resolve(fullOutput));
|
|
47479
47825
|
}, idleTimeoutMs);
|
|
47480
47826
|
};
|
|
47481
47827
|
/**
|
|
@@ -47529,41 +47875,43 @@
|
|
|
47529
47875
|
* Handles process exit and resolves or rejects accordingly.
|
|
47530
47876
|
*/
|
|
47531
47877
|
const handleExit = (code) => {
|
|
47532
|
-
|
|
47533
|
-
|
|
47878
|
+
const failure = code === 0 || markerSeen ? undefined : new Error(buildCommandFailureMessage(scriptPathPosix, code, fullOutput));
|
|
47879
|
+
const status = failure ? `failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}` : 'succeeded';
|
|
47880
|
+
settleWithLog(status, () => {
|
|
47881
|
+
if (!failure) {
|
|
47534
47882
|
resolve(fullOutput);
|
|
47535
47883
|
return;
|
|
47536
47884
|
}
|
|
47537
|
-
reject(
|
|
47885
|
+
reject(failure);
|
|
47538
47886
|
});
|
|
47539
47887
|
};
|
|
47540
47888
|
commandProcess.on('close', handleExit);
|
|
47541
47889
|
commandProcess.on('exit', handleExit);
|
|
47542
47890
|
commandProcess.on('disconnect', () => {
|
|
47543
|
-
|
|
47544
|
-
|
|
47545
|
-
});
|
|
47891
|
+
const failure = new Error(buildCommandFailureMessage(scriptPathPosix, null, fullOutput));
|
|
47892
|
+
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
47546
47893
|
});
|
|
47547
47894
|
commandProcess.on('error', (error) => {
|
|
47548
|
-
|
|
47549
|
-
|
|
47550
|
-
|
|
47551
|
-
|
|
47552
|
-
});
|
|
47895
|
+
const outputSnippet = createOutputSnippet(fullOutput);
|
|
47896
|
+
const details = outputSnippet ? `\n\n${outputSnippet}` : '';
|
|
47897
|
+
const failure = new Error(`Command "bash ${scriptPathPosix}" failed: ${error.message}${details}`);
|
|
47898
|
+
settleWithLog('failed before completion', () => reject(failure), failure);
|
|
47553
47899
|
});
|
|
47554
47900
|
});
|
|
47555
47901
|
}
|
|
47556
47902
|
|
|
47557
47903
|
/**
|
|
47558
|
-
* Creates a temporary script file, runs it, waits for a completion marker and idle time, and
|
|
47904
|
+
* Creates a temporary script file, runs it, waits for a completion marker and idle time, and defers cleanup when a round tracker is provided.
|
|
47559
47905
|
* Returns the captured output for post-processing.
|
|
47560
47906
|
*/
|
|
47561
47907
|
async function $runGoScriptUntilMarkerIdle(options) {
|
|
47562
47908
|
return await withTempScript(options, async (scriptPath) => {
|
|
47563
47909
|
return await runScriptUntilMarkerIdle({
|
|
47564
47910
|
scriptPath,
|
|
47911
|
+
scriptContent: options.scriptContent,
|
|
47565
47912
|
completionLineMatcher: options.completionLineMatcher,
|
|
47566
47913
|
idleTimeoutMs: options.idleTimeoutMs,
|
|
47914
|
+
logPath: options.logPath,
|
|
47567
47915
|
});
|
|
47568
47916
|
});
|
|
47569
47917
|
}
|
|
@@ -47941,6 +48289,8 @@
|
|
|
47941
48289
|
scriptContent,
|
|
47942
48290
|
completionLineMatcher: CODEX_COMPLETION_LINE,
|
|
47943
48291
|
idleTimeoutMs: CODEX_COMPLETION_IDLE_MS,
|
|
48292
|
+
logPath: options.logPath,
|
|
48293
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
47944
48294
|
});
|
|
47945
48295
|
this.rateLimitBackoff.reset();
|
|
47946
48296
|
return { usage: buildCodexUsageFromOutput(output, this.options.model) };
|
|
@@ -48074,6 +48424,8 @@
|
|
|
48074
48424
|
output = await $runGoScriptWithOutput({
|
|
48075
48425
|
scriptPath: options.scriptPath,
|
|
48076
48426
|
scriptContent,
|
|
48427
|
+
logPath: options.logPath,
|
|
48428
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
48077
48429
|
});
|
|
48078
48430
|
}
|
|
48079
48431
|
catch (error) {
|
|
@@ -48100,6 +48452,7 @@
|
|
|
48100
48452
|
cd "${projectPath}"
|
|
48101
48453
|
${options.command}
|
|
48102
48454
|
`),
|
|
48455
|
+
logPath: options.logPath,
|
|
48103
48456
|
});
|
|
48104
48457
|
}
|
|
48105
48458
|
|
|
@@ -48123,6 +48476,8 @@
|
|
|
48123
48476
|
prompt: options.prompt,
|
|
48124
48477
|
scriptPath: options.scriptPath,
|
|
48125
48478
|
projectPath: options.projectPath,
|
|
48479
|
+
logPath: options.logPath,
|
|
48480
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
48126
48481
|
});
|
|
48127
48482
|
return { ...result, attemptCount: 1 };
|
|
48128
48483
|
}
|
|
@@ -48134,6 +48489,8 @@
|
|
|
48134
48489
|
prompt: promptForCurrentAttempt,
|
|
48135
48490
|
scriptPath: options.scriptPath,
|
|
48136
48491
|
projectPath: options.projectPath,
|
|
48492
|
+
logPath: options.logPath,
|
|
48493
|
+
promptRoundArtifacts: options.promptRoundArtifacts,
|
|
48137
48494
|
});
|
|
48138
48495
|
console.info(colors__default["default"].gray(`Running verification command after attempt #${attemptCount}: ${normalizedTestCommand}`));
|
|
48139
48496
|
try {
|
|
@@ -48141,6 +48498,7 @@
|
|
|
48141
48498
|
command: normalizedTestCommand,
|
|
48142
48499
|
projectPath: options.projectPath,
|
|
48143
48500
|
scriptPath: buildPromptTestScriptPath(options.scriptPath),
|
|
48501
|
+
logPath: options.logPath,
|
|
48144
48502
|
});
|
|
48145
48503
|
return { ...result, attemptCount };
|
|
48146
48504
|
}
|
|
@@ -48978,6 +49336,7 @@
|
|
|
48978
49336
|
const codexPrompt = appendCoderContext(buildCodexPrompt(nextPrompt.file, nextPrompt.section), resolvedCoderContext);
|
|
48979
49337
|
const scriptPath = buildScriptPath(nextPrompt.file, nextPrompt.section);
|
|
48980
49338
|
const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section);
|
|
49339
|
+
const promptRoundArtifacts = createCoderRunPromptRoundArtifacts(options.preserveLogs);
|
|
48981
49340
|
if (isUiMode) {
|
|
48982
49341
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentPrompt(promptLabel);
|
|
48983
49342
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('running');
|
|
@@ -48988,57 +49347,68 @@
|
|
|
48988
49347
|
}
|
|
48989
49348
|
const promptExecutionStartedDate = moment__default["default"]();
|
|
48990
49349
|
let attemptCount = 1;
|
|
49350
|
+
let promptRoundOutcome = 'failure';
|
|
48991
49351
|
const roundChangedFilesSnapshot = options.normalizeLineEndings
|
|
48992
49352
|
? await captureChangedFilesSnapshot(process.cwd())
|
|
48993
49353
|
: undefined;
|
|
48994
49354
|
try {
|
|
48995
|
-
|
|
48996
|
-
|
|
48997
|
-
|
|
48998
|
-
|
|
48999
|
-
|
|
49000
|
-
|
|
49001
|
-
|
|
49002
|
-
|
|
49003
|
-
|
|
49004
|
-
|
|
49005
|
-
|
|
49006
|
-
|
|
49007
|
-
|
|
49008
|
-
|
|
49355
|
+
await withPromptRuntimeLog(scriptPath, async (logPath) => {
|
|
49356
|
+
try {
|
|
49357
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
49358
|
+
const result = await runPromptWithTestFeedback({
|
|
49359
|
+
runner,
|
|
49360
|
+
prompt: codexPrompt,
|
|
49361
|
+
scriptPath,
|
|
49362
|
+
projectPath: process.cwd(),
|
|
49363
|
+
promptLabel,
|
|
49364
|
+
testCommand: options.testCommand,
|
|
49365
|
+
logPath,
|
|
49366
|
+
promptRoundArtifacts,
|
|
49367
|
+
onAttemptStarted: (nextAttemptCount) => {
|
|
49368
|
+
attemptCount = nextAttemptCount;
|
|
49369
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(nextAttemptCount);
|
|
49370
|
+
if (nextAttemptCount > 1) {
|
|
49371
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Retrying (attempt ${nextAttemptCount})`);
|
|
49372
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('verifying');
|
|
49373
|
+
}
|
|
49374
|
+
},
|
|
49375
|
+
});
|
|
49376
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
49377
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Committing changes');
|
|
49378
|
+
markPromptDone(nextPrompt.file, nextPrompt.section, result.usage, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, result.attemptCount);
|
|
49379
|
+
await writePromptFile(nextPrompt.file);
|
|
49380
|
+
await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
|
|
49381
|
+
if (options.waitForUser) {
|
|
49382
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
49383
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Waiting... Press Enter to commit');
|
|
49384
|
+
printCommitMessage(commitMessage);
|
|
49385
|
+
await waitForEnter(colors__default["default"].bgWhite('Press Enter to commit and continue...'));
|
|
49386
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
49009
49387
|
}
|
|
49010
|
-
|
|
49011
|
-
|
|
49012
|
-
|
|
49013
|
-
|
|
49014
|
-
|
|
49015
|
-
|
|
49016
|
-
|
|
49017
|
-
|
|
49018
|
-
|
|
49019
|
-
|
|
49020
|
-
|
|
49021
|
-
|
|
49022
|
-
|
|
49023
|
-
|
|
49024
|
-
|
|
49025
|
-
|
|
49388
|
+
await commitChanges(commitMessage, { autoPush: options.autoPush });
|
|
49389
|
+
await runPostPromptAutoMigrationIfEnabled(options);
|
|
49390
|
+
promptRoundOutcome = 'success';
|
|
49391
|
+
}
|
|
49392
|
+
catch (error) {
|
|
49393
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
49394
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('error');
|
|
49395
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(error instanceof Error ? error.message : String(error));
|
|
49396
|
+
markPromptFailed(nextPrompt.file, nextPrompt.section, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, attemptCount);
|
|
49397
|
+
await writePromptFile(nextPrompt.file);
|
|
49398
|
+
await writePromptErrorLog({
|
|
49399
|
+
file: nextPrompt.file,
|
|
49400
|
+
section: nextPrompt.section,
|
|
49401
|
+
runnerName: runnerMetadata.runnerName,
|
|
49402
|
+
modelName: runnerMetadata.modelName,
|
|
49403
|
+
error,
|
|
49404
|
+
});
|
|
49405
|
+
await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
|
|
49406
|
+
throw error;
|
|
49407
|
+
}
|
|
49408
|
+
}, promptRoundArtifacts);
|
|
49026
49409
|
}
|
|
49027
|
-
|
|
49028
|
-
|
|
49029
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('error');
|
|
49030
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(error instanceof Error ? error.message : String(error));
|
|
49031
|
-
markPromptFailed(nextPrompt.file, nextPrompt.section, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, attemptCount);
|
|
49032
|
-
await writePromptFile(nextPrompt.file);
|
|
49033
|
-
await writePromptErrorLog({
|
|
49034
|
-
file: nextPrompt.file,
|
|
49035
|
-
section: nextPrompt.section,
|
|
49036
|
-
runnerName: runnerMetadata.runnerName,
|
|
49037
|
-
modelName: runnerMetadata.modelName,
|
|
49038
|
-
error,
|
|
49039
|
-
});
|
|
49040
|
-
await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
|
|
49041
|
-
throw error;
|
|
49410
|
+
finally {
|
|
49411
|
+
await promptRoundArtifacts.cleanup(promptRoundOutcome);
|
|
49042
49412
|
}
|
|
49043
49413
|
}
|
|
49044
49414
|
}
|