@promptbook/cli 0.112.0-44 → 0.112.0-45
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 +675 -491
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/CoderRunTimer.d.ts +31 -0
- package/esm/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +23 -0
- package/esm/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +13 -4
- package/esm/scripts/run-codex-prompts/common/progressFormatting.d.ts +16 -0
- 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/shouldDeleteTemporaryArtifact.d.ts +7 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/withPromptRuntimeLog.d.ts +4 -3
- 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/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +15 -20
- package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +28 -0
- package/esm/scripts/run-codex-prompts/ui/renderCoderRunUi.d.ts +2 -0
- package/esm/src/avatars/Avatar.d.ts +7 -0
- package/esm/src/avatars/avatarRenderingUtils.d.ts +117 -0
- package/esm/src/avatars/index.d.ts +6 -0
- package/esm/src/avatars/renderAvatarVisual.d.ts +9 -0
- package/esm/src/avatars/types/AvatarDefinition.d.ts +20 -0
- package/esm/src/avatars/types/AvatarVisualDefinition.d.ts +96 -0
- package/esm/src/avatars/visuals/avatarVisualRegistry.d.ts +16 -0
- package/esm/src/avatars/visuals/minecraftAvatarVisual.d.ts +7 -0
- package/esm/src/avatars/visuals/octopusAvatarVisual.d.ts +7 -0
- package/esm/src/avatars/visuals/pixelArtAvatarVisual.d.ts +7 -0
- package/esm/src/commitments/STYLE/STYLE.d.ts +9 -2
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/umd/index.umd.js +675 -491
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/CoderRunTimer.d.ts +31 -0
- package/umd/scripts/run-codex-prompts/common/buildCoderRunProgressSnapshot.d.ts +23 -0
- package/umd/scripts/run-codex-prompts/common/cliProgressDisplay.d.ts +13 -4
- package/umd/scripts/run-codex-prompts/common/progressFormatting.d.ts +16 -0
- 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/shouldDeleteTemporaryArtifact.d.ts +7 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/withPromptRuntimeLog.d.ts +4 -3
- 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/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +15 -20
- package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +28 -0
- package/umd/scripts/run-codex-prompts/ui/renderCoderRunUi.d.ts +2 -0
- package/umd/src/avatars/Avatar.d.ts +7 -0
- package/umd/src/avatars/avatarRenderingUtils.d.ts +117 -0
- package/umd/src/avatars/index.d.ts +6 -0
- package/umd/src/avatars/renderAvatarVisual.d.ts +9 -0
- package/umd/src/avatars/types/AvatarDefinition.d.ts +20 -0
- package/umd/src/avatars/types/AvatarVisualDefinition.d.ts +96 -0
- package/umd/src/avatars/visuals/avatarVisualRegistry.d.ts +16 -0
- package/umd/src/avatars/visuals/minecraftAvatarVisual.d.ts +7 -0
- package/umd/src/avatars/visuals/octopusAvatarVisual.d.ts +7 -0
- package/umd/src/avatars/visuals/pixelArtAvatarVisual.d.ts +7 -0
- package/umd/src/commitments/STYLE/STYLE.d.ts +9 -2
- package/umd/src/version.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/common/runGoScript/PromptRoundArtifacts.d.ts +0 -35
- package/umd/scripts/run-codex-prompts/common/runGoScript/PromptRoundArtifacts.d.ts +0 -35
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-45';
|
|
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
|
|
@@ -3007,6 +3007,8 @@
|
|
|
3007
3007
|
Features:
|
|
3008
3008
|
- Automatically stages and commits changes with agent identity
|
|
3009
3009
|
- Optional post-commit git push with explicit --auto-push opt-in
|
|
3010
|
+
- Optional --preserve-logs keeps temp prompt/log artifacts after successful rounds
|
|
3011
|
+
- Optional --no-ui keeps plain streaming console output for logging and debugging
|
|
3010
3012
|
- Supports GPG signing of commits
|
|
3011
3013
|
- Optional post-prompt verification with test-feedback retries
|
|
3012
3014
|
- Progress tracking and interactive controls
|
|
@@ -3022,19 +3024,21 @@
|
|
|
3022
3024
|
`));
|
|
3023
3025
|
command.option('--context <context-or-file>', 'Append extra instructions either inline or from a file path relative to the current project');
|
|
3024
3026
|
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
3027
|
+
command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
|
|
3028
|
+
command.option('--no-ui', 'Disable the rich terminal UI and keep plain streaming console output for logging and debugging');
|
|
3025
3029
|
command.addOption(new commander.Option('--thinking-level <thinking-level>', `Set reasoning effort for supported runners (${THINKING_LEVEL_VALUES.join(', ')})`).choices([...THINKING_LEVEL_VALUES]));
|
|
3026
3030
|
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
|
|
3027
3031
|
command.option('--no-wait', 'Skip user prompts between processing');
|
|
3028
3032
|
command.option('--ignore-git-changes', 'Skip clean working tree check before running prompts', false);
|
|
3029
3033
|
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);
|
|
3031
3034
|
command.option('--no-normalize-line-endings', 'Disable automatic LF normalization for files changed in each coding round');
|
|
3032
3035
|
command.option('--auto-push', 'Automatically git push after each commit', false);
|
|
3033
3036
|
command.option('--auto-migrate', 'Run testing-server database migrations automatically after each successfully processed prompt');
|
|
3034
3037
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
3035
3038
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
3036
|
-
const { dryRun, agent, model, context, test, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits,
|
|
3039
|
+
const { dryRun, agent, model, context, test, preserveLogs, ui, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits, normalizeLineEndings, autoMigrate, allowDestructiveAutoMigrate, autoPush, } = cliOptions;
|
|
3037
3040
|
const testCommand = normalizeCommandOptionValue(test);
|
|
3041
|
+
const noUi = !ui;
|
|
3038
3042
|
// Validate agent
|
|
3039
3043
|
let agentName = undefined;
|
|
3040
3044
|
if (agent) {
|
|
@@ -3064,11 +3068,12 @@
|
|
|
3064
3068
|
model,
|
|
3065
3069
|
context,
|
|
3066
3070
|
testCommand,
|
|
3071
|
+
preserveLogs,
|
|
3072
|
+
noUi,
|
|
3067
3073
|
thinkingLevel,
|
|
3068
3074
|
priority,
|
|
3069
3075
|
normalizeLineEndings,
|
|
3070
3076
|
allowCredits,
|
|
3071
|
-
preserveLogs,
|
|
3072
3077
|
autoMigrate,
|
|
3073
3078
|
allowDestructiveAutoMigrate,
|
|
3074
3079
|
autoPush,
|
|
@@ -18388,7 +18393,7 @@
|
|
|
18388
18393
|
DELETE Casual conversational style
|
|
18389
18394
|
REMOVE All emoji usage
|
|
18390
18395
|
GOAL Provide professional business communications
|
|
18391
|
-
|
|
18396
|
+
WRITING RULES Use formal language and proper business etiquette
|
|
18392
18397
|
\`\`\`
|
|
18393
18398
|
|
|
18394
18399
|
\`\`\`book
|
|
@@ -18399,7 +18404,7 @@
|
|
|
18399
18404
|
DISCARD Technical jargon explanations
|
|
18400
18405
|
CANCEL Advanced troubleshooting procedures
|
|
18401
18406
|
GOAL Help users with simple, easy-to-follow solutions
|
|
18402
|
-
|
|
18407
|
+
WRITING RULES Use plain language that anyone can understand
|
|
18403
18408
|
\`\`\`
|
|
18404
18409
|
|
|
18405
18410
|
\`\`\`book
|
|
@@ -18416,11 +18421,11 @@
|
|
|
18416
18421
|
Concise Information Provider
|
|
18417
18422
|
|
|
18418
18423
|
PERSONA You are a helpful assistant who provides detailed explanations
|
|
18419
|
-
|
|
18424
|
+
WRITING RULES Include examples, analogies, and comprehensive context
|
|
18420
18425
|
CANCEL Detailed explanation style
|
|
18421
18426
|
DISCARD Examples and analogies
|
|
18422
18427
|
GOAL Provide brief, direct answers without unnecessary elaboration
|
|
18423
|
-
|
|
18428
|
+
WRITING RULES Be concise and to the point
|
|
18424
18429
|
\`\`\`
|
|
18425
18430
|
`);
|
|
18426
18431
|
}
|
|
@@ -18604,7 +18609,7 @@
|
|
|
18604
18609
|
PERSONA You are a data analysis expert
|
|
18605
18610
|
FORMAT Present results in structured tables
|
|
18606
18611
|
FORMAT Include confidence scores for all predictions
|
|
18607
|
-
|
|
18612
|
+
WRITING RULES Be concise and precise in explanations
|
|
18608
18613
|
\`\`\`
|
|
18609
18614
|
`);
|
|
18610
18615
|
}
|
|
@@ -18998,7 +19003,7 @@
|
|
|
18998
19003
|
|
|
18999
19004
|
GOAL Help students understand mathematical concepts clearly
|
|
19000
19005
|
GOAL Ensure all explanations are age-appropriate and accessible
|
|
19001
|
-
|
|
19006
|
+
WRITING RULES Use simple language and provide step-by-step explanations
|
|
19002
19007
|
\`\`\`
|
|
19003
19008
|
|
|
19004
19009
|
\`\`\`book
|
|
@@ -19412,7 +19417,7 @@
|
|
|
19412
19417
|
KNOWLEDGE Academic research requires careful citation and verification
|
|
19413
19418
|
KNOWLEDGE https://example.com/research-guidelines.pdf
|
|
19414
19419
|
ACTION Can help with literature reviews and data analysis
|
|
19415
|
-
|
|
19420
|
+
WRITING RULES Present information in clear, academic format
|
|
19416
19421
|
\`\`\`
|
|
19417
19422
|
`);
|
|
19418
19423
|
}
|
|
@@ -21163,7 +21168,7 @@
|
|
|
21163
21168
|
|
|
21164
21169
|
META IMAGE https://example.com/professional-avatar.jpg
|
|
21165
21170
|
PERSONA You are a professional business assistant
|
|
21166
|
-
|
|
21171
|
+
WRITING RULES Maintain a formal and courteous tone
|
|
21167
21172
|
\`\`\`
|
|
21168
21173
|
|
|
21169
21174
|
\`\`\`book
|
|
@@ -21171,7 +21176,7 @@
|
|
|
21171
21176
|
|
|
21172
21177
|
META IMAGE /assets/creative-bot-avatar.png
|
|
21173
21178
|
PERSONA You are a creative and inspiring assistant
|
|
21174
|
-
|
|
21179
|
+
WRITING RULES Be enthusiastic and encouraging
|
|
21175
21180
|
ACTION Can help with brainstorming and ideation
|
|
21176
21181
|
\`\`\`
|
|
21177
21182
|
`);
|
|
@@ -21330,7 +21335,7 @@
|
|
|
21330
21335
|
META LINK https://twitter.com/devhandle
|
|
21331
21336
|
PERSONA You are an experienced open source developer
|
|
21332
21337
|
ACTION Can help with code reviews and architecture decisions
|
|
21333
|
-
|
|
21338
|
+
WRITING RULES Be direct and technical in explanations
|
|
21334
21339
|
\`\`\`
|
|
21335
21340
|
`);
|
|
21336
21341
|
}
|
|
@@ -21536,7 +21541,7 @@
|
|
|
21536
21541
|
MODEL TEMPERATURE 0.8
|
|
21537
21542
|
MODEL TOP_P 0.9
|
|
21538
21543
|
MODEL MAX_TOKENS 2048
|
|
21539
|
-
|
|
21544
|
+
WRITING RULES Be imaginative and expressive
|
|
21540
21545
|
ACTION Can help with storytelling and character development
|
|
21541
21546
|
\`\`\`
|
|
21542
21547
|
|
|
@@ -21748,7 +21753,7 @@
|
|
|
21748
21753
|
NOTE Uses RAG for accessing latest research papers
|
|
21749
21754
|
PERSONA You are a knowledgeable research assistant
|
|
21750
21755
|
ACTION Can help with literature reviews and citations
|
|
21751
|
-
|
|
21756
|
+
WRITING RULES Present information in academic format
|
|
21752
21757
|
\`\`\`
|
|
21753
21758
|
`);
|
|
21754
21759
|
}
|
|
@@ -22042,7 +22047,7 @@
|
|
|
22042
22047
|
RULE Always ask for clarification if the user's request is ambiguous
|
|
22043
22048
|
RULE Be polite and professional in all interactions
|
|
22044
22049
|
RULES Never provide medical or legal advice
|
|
22045
|
-
|
|
22050
|
+
WRITING RULES Maintain a friendly and helpful tone
|
|
22046
22051
|
\`\`\`
|
|
22047
22052
|
|
|
22048
22053
|
\`\`\`book
|
|
@@ -22311,8 +22316,8 @@
|
|
|
22311
22316
|
/**
|
|
22312
22317
|
* STYLE commitment definition
|
|
22313
22318
|
*
|
|
22314
|
-
*
|
|
22315
|
-
*
|
|
22319
|
+
* Deprecated legacy writing-style commitment kept for backward compatibility.
|
|
22320
|
+
* New books should prefer `WRITING RULES` for writing-only constraints.
|
|
22316
22321
|
*
|
|
22317
22322
|
* Example usage in agent source:
|
|
22318
22323
|
*
|
|
@@ -22331,7 +22336,16 @@
|
|
|
22331
22336
|
* Short one-line description of STYLE.
|
|
22332
22337
|
*/
|
|
22333
22338
|
get description() {
|
|
22334
|
-
return '
|
|
22339
|
+
return 'Deprecated legacy writing-style commitment. Prefer `WRITING RULES` for new books.';
|
|
22340
|
+
}
|
|
22341
|
+
/**
|
|
22342
|
+
* Optional UI/docs-only deprecation metadata.
|
|
22343
|
+
*/
|
|
22344
|
+
get deprecation() {
|
|
22345
|
+
return {
|
|
22346
|
+
message: 'Use `WRITING RULES` for writing-only constraints such as tone, length, formatting, or emoji usage.',
|
|
22347
|
+
replacedBy: ['WRITING RULES'],
|
|
22348
|
+
};
|
|
22335
22349
|
}
|
|
22336
22350
|
/**
|
|
22337
22351
|
* Icon for this commitment.
|
|
@@ -22346,15 +22360,34 @@
|
|
|
22346
22360
|
return _spaceTrim.spaceTrim(`
|
|
22347
22361
|
# ${this.type}
|
|
22348
22362
|
|
|
22349
|
-
|
|
22363
|
+
Deprecated legacy commitment for writing and presentation instructions.
|
|
22364
|
+
|
|
22365
|
+
## Migration
|
|
22366
|
+
|
|
22367
|
+
- Existing \`${this.type}\` books still parse and compile.
|
|
22368
|
+
- New books should prefer \`WRITING RULES\`.
|
|
22369
|
+
- Use \`WRITING SAMPLE\` when you want to anchor voice by example instead of stating constraints directly.
|
|
22370
|
+
- The plural alias \`STYLES\` is the same legacy commitment family.
|
|
22350
22371
|
|
|
22351
22372
|
## Key aspects
|
|
22352
22373
|
|
|
22353
|
-
-
|
|
22374
|
+
- \`${this.type}\` remains functional for backward compatibility only.
|
|
22354
22375
|
- Later style instructions can override earlier ones.
|
|
22355
22376
|
- Style affects both tone and presentation format.
|
|
22356
22377
|
|
|
22357
|
-
##
|
|
22378
|
+
## Preferred replacement
|
|
22379
|
+
|
|
22380
|
+
\`\`\`book
|
|
22381
|
+
Technical Writer
|
|
22382
|
+
|
|
22383
|
+
GOAL Help the user understand technical topics with practical, accurate guidance.
|
|
22384
|
+
WRITING RULES Write in a professional but friendly tone.
|
|
22385
|
+
WRITING RULES Use bullet points for lists.
|
|
22386
|
+
WRITING RULES Always provide code examples when explaining programming concepts.
|
|
22387
|
+
FORMAT Use markdown formatting with clear headings
|
|
22388
|
+
\`\`\`
|
|
22389
|
+
|
|
22390
|
+
## Legacy compatibility examples
|
|
22358
22391
|
|
|
22359
22392
|
\`\`\`book
|
|
22360
22393
|
Technical Writer
|
|
@@ -23095,7 +23128,7 @@
|
|
|
23095
23128
|
|
|
23096
23129
|
PERSONA You are a helpful customer support representative
|
|
23097
23130
|
TEMPLATE Always structure your response with: 1) Acknowledgment, 2) Solution, 3) Follow-up question
|
|
23098
|
-
|
|
23131
|
+
WRITING RULES Be professional and empathetic
|
|
23099
23132
|
\`\`\`
|
|
23100
23133
|
|
|
23101
23134
|
\`\`\`book
|
|
@@ -23539,7 +23572,7 @@
|
|
|
23539
23572
|
|
|
23540
23573
|
PERSONA You are a news analyst who stays up-to-date with current events
|
|
23541
23574
|
USE BROWSER
|
|
23542
|
-
|
|
23575
|
+
WRITING RULES Present news in a balanced and objective manner
|
|
23543
23576
|
ACTION Can search for and summarize news articles
|
|
23544
23577
|
\`\`\`
|
|
23545
23578
|
|
|
@@ -44245,7 +44278,7 @@
|
|
|
44245
44278
|
/**
|
|
44246
44279
|
* CLI usage text for this script.
|
|
44247
44280
|
*/
|
|
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] [--
|
|
44281
|
+
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--agent <agent-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--preserve-logs] [--no-ui] [--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]';
|
|
44249
44282
|
/**
|
|
44250
44283
|
* Top-level flags supported by this command.
|
|
44251
44284
|
*/
|
|
@@ -44255,10 +44288,11 @@
|
|
|
44255
44288
|
'--model',
|
|
44256
44289
|
'--context',
|
|
44257
44290
|
'--test',
|
|
44291
|
+
'--preserve-logs',
|
|
44292
|
+
'--no-ui',
|
|
44258
44293
|
'--thinking-level',
|
|
44259
44294
|
'--priority',
|
|
44260
44295
|
'--allow-credits',
|
|
44261
|
-
'--preserve-logs',
|
|
44262
44296
|
'--auto-migrate',
|
|
44263
44297
|
'--allow-destructive-auto-migrate',
|
|
44264
44298
|
'--no-wait',
|
|
@@ -44288,6 +44322,8 @@
|
|
|
44288
44322
|
const context = readOptionValue(args, '--context');
|
|
44289
44323
|
const hasTestCommandFlag = args.includes('--test');
|
|
44290
44324
|
const testCommand = readVariadicOptionValue(args, '--test');
|
|
44325
|
+
const preserveLogs = args.includes('--preserve-logs');
|
|
44326
|
+
const noUi = args.includes('--no-ui');
|
|
44291
44327
|
const hasThinkingLevelFlag = args.includes('--thinking-level');
|
|
44292
44328
|
const thinkingLevelValue = readOptionValue(args, '--thinking-level');
|
|
44293
44329
|
const hasPriorityFlag = args.includes('--priority');
|
|
@@ -44295,7 +44331,6 @@
|
|
|
44295
44331
|
const ignoreGitChanges = args.includes('--ignore-git-changes');
|
|
44296
44332
|
const normalizeLineEndings = !args.includes('--no-normalize-line-endings');
|
|
44297
44333
|
const allowCredits = args.includes('--allow-credits');
|
|
44298
|
-
const preserveLogs = args.includes('--preserve-logs');
|
|
44299
44334
|
const autoMigrate = args.includes('--auto-migrate');
|
|
44300
44335
|
const allowDestructiveAutoMigrate = args.includes('--allow-destructive-auto-migrate');
|
|
44301
44336
|
const autoPush = args.includes('--auto-push');
|
|
@@ -44321,10 +44356,11 @@
|
|
|
44321
44356
|
ignoreGitChanges,
|
|
44322
44357
|
normalizeLineEndings,
|
|
44323
44358
|
allowCredits,
|
|
44324
|
-
preserveLogs,
|
|
44325
44359
|
autoMigrate,
|
|
44326
44360
|
allowDestructiveAutoMigrate,
|
|
44327
44361
|
autoPush,
|
|
44362
|
+
preserveLogs,
|
|
44363
|
+
noUi,
|
|
44328
44364
|
agentName,
|
|
44329
44365
|
model,
|
|
44330
44366
|
context,
|
|
@@ -44405,18 +44441,10 @@
|
|
|
44405
44441
|
return `${normalizedPrompt}\n\n${normalizedContext}`;
|
|
44406
44442
|
}
|
|
44407
44443
|
|
|
44408
|
-
/**
|
|
44409
|
-
* Refresh interval for the progress header in milliseconds.
|
|
44410
|
-
*/
|
|
44411
|
-
const PROGRESS_REFRESH_INTERVAL_MS = 1000;
|
|
44412
|
-
/**
|
|
44413
|
-
* Number of terminal lines reserved for the sticky progress header.
|
|
44414
|
-
*/
|
|
44415
|
-
const PROGRESS_HEADER_RESERVED_LINES = 1;
|
|
44416
44444
|
/**
|
|
44417
44445
|
* Calendar formats used when displaying the estimated completion time.
|
|
44418
44446
|
*/
|
|
44419
|
-
const ESTIMATED_DONE_CALENDAR_FORMATS
|
|
44447
|
+
const ESTIMATED_DONE_CALENDAR_FORMATS = {
|
|
44420
44448
|
sameDay: '[Today] h:mm',
|
|
44421
44449
|
nextDay: '[Tomorrow] h:mm',
|
|
44422
44450
|
nextWeek: 'dddd h:mm',
|
|
@@ -44424,6 +44452,121 @@
|
|
|
44424
44452
|
lastWeek: 'dddd h:mm',
|
|
44425
44453
|
sameElse: 'MMM D h:mm',
|
|
44426
44454
|
};
|
|
44455
|
+
/**
|
|
44456
|
+
* Formats a duration into a compact string such as "3h 12m" or "45s".
|
|
44457
|
+
*/
|
|
44458
|
+
function formatDurationBrief(duration) {
|
|
44459
|
+
const totalSeconds = Math.max(0, Math.round(duration.asSeconds()));
|
|
44460
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
44461
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
44462
|
+
const seconds = totalSeconds % 60;
|
|
44463
|
+
const parts = [];
|
|
44464
|
+
if (hours > 0) {
|
|
44465
|
+
parts.push(`${hours}h`);
|
|
44466
|
+
}
|
|
44467
|
+
if (minutes > 0) {
|
|
44468
|
+
parts.push(`${minutes}m`);
|
|
44469
|
+
}
|
|
44470
|
+
if (!parts.length && seconds > 0) {
|
|
44471
|
+
parts.push(`${seconds}s`);
|
|
44472
|
+
}
|
|
44473
|
+
if (!parts.length) {
|
|
44474
|
+
parts.push('0s');
|
|
44475
|
+
}
|
|
44476
|
+
return parts.join(' ');
|
|
44477
|
+
}
|
|
44478
|
+
|
|
44479
|
+
/**
|
|
44480
|
+
* Builds a session-scoped progress snapshot from prompt stats and elapsed active time.
|
|
44481
|
+
*/
|
|
44482
|
+
function buildCoderRunProgressSnapshot(stats, elapsedDuration, initialDone) {
|
|
44483
|
+
const totalPrompts = stats.done + stats.forAgent + stats.toBeWritten;
|
|
44484
|
+
const sessionDone = Math.max(0, stats.done - initialDone);
|
|
44485
|
+
const sessionRemaining = stats.forAgent;
|
|
44486
|
+
const sessionTotal = sessionDone + sessionRemaining;
|
|
44487
|
+
const currentPromptIndex = sessionTotal > 0 ? Math.min(sessionDone + 1, sessionTotal) : 0;
|
|
44488
|
+
const percentage = sessionTotal > 0 ? Math.round((sessionDone / sessionTotal) * 100) : 0;
|
|
44489
|
+
const elapsedText = formatDurationBrief(elapsedDuration);
|
|
44490
|
+
let estimatedTotalText = 'estimating...';
|
|
44491
|
+
let estimatedLabel = 'after first completion';
|
|
44492
|
+
let isEstimatedTotalKnown = false;
|
|
44493
|
+
if (sessionTotal > 0 && sessionDone > 0) {
|
|
44494
|
+
const estimatedTotalMs = (elapsedDuration.asMilliseconds() * sessionTotal) / sessionDone;
|
|
44495
|
+
const estimatedRemainingMs = Math.max(0, estimatedTotalMs - elapsedDuration.asMilliseconds());
|
|
44496
|
+
const estimatedTotalDuration = moment__default["default"].duration(estimatedTotalMs);
|
|
44497
|
+
const estimatedCompletion = moment__default["default"]().add(estimatedRemainingMs, 'milliseconds');
|
|
44498
|
+
estimatedTotalText = formatDurationBrief(estimatedTotalDuration);
|
|
44499
|
+
estimatedLabel = estimatedCompletion.calendar(null, ESTIMATED_DONE_CALENDAR_FORMATS);
|
|
44500
|
+
isEstimatedTotalKnown = true;
|
|
44501
|
+
}
|
|
44502
|
+
return {
|
|
44503
|
+
totalPrompts,
|
|
44504
|
+
sessionDone,
|
|
44505
|
+
sessionRemaining,
|
|
44506
|
+
sessionTotal,
|
|
44507
|
+
currentPromptIndex,
|
|
44508
|
+
skippedPrompts: stats.belowMinimumPriority,
|
|
44509
|
+
toBeWrittenPrompts: stats.toBeWritten,
|
|
44510
|
+
percentage,
|
|
44511
|
+
elapsedText,
|
|
44512
|
+
estimatedTotalText,
|
|
44513
|
+
estimatedLabel,
|
|
44514
|
+
isEstimatedTotalKnown,
|
|
44515
|
+
};
|
|
44516
|
+
}
|
|
44517
|
+
|
|
44518
|
+
/**
|
|
44519
|
+
* Tracks active coder-run time while excluding pauses and user-confirmation waits.
|
|
44520
|
+
*/
|
|
44521
|
+
class CoderRunTimer {
|
|
44522
|
+
/**
|
|
44523
|
+
* Creates a timer anchored at the provided start time.
|
|
44524
|
+
*/
|
|
44525
|
+
constructor(startTime, isPausedInitially = false) {
|
|
44526
|
+
this.startTime = startTime;
|
|
44527
|
+
/**
|
|
44528
|
+
* Total milliseconds spent in paused state across the run.
|
|
44529
|
+
*/
|
|
44530
|
+
this.pausedMs = 0;
|
|
44531
|
+
if (isPausedInitially) {
|
|
44532
|
+
this.pausedSince = startTime.clone();
|
|
44533
|
+
}
|
|
44534
|
+
}
|
|
44535
|
+
/**
|
|
44536
|
+
* Pauses active-time tracking until `resume()` is called.
|
|
44537
|
+
*/
|
|
44538
|
+
pause() {
|
|
44539
|
+
if (this.pausedSince === undefined) {
|
|
44540
|
+
this.pausedSince = moment__default["default"]();
|
|
44541
|
+
}
|
|
44542
|
+
}
|
|
44543
|
+
/**
|
|
44544
|
+
* Resumes active-time tracking after a pause.
|
|
44545
|
+
*/
|
|
44546
|
+
resume() {
|
|
44547
|
+
if (this.pausedSince !== undefined) {
|
|
44548
|
+
this.pausedMs += moment__default["default"]().diff(this.pausedSince);
|
|
44549
|
+
this.pausedSince = undefined;
|
|
44550
|
+
}
|
|
44551
|
+
}
|
|
44552
|
+
/**
|
|
44553
|
+
* Returns the currently accumulated active duration.
|
|
44554
|
+
*/
|
|
44555
|
+
getElapsedDuration() {
|
|
44556
|
+
const wallMs = moment__default["default"]().diff(this.startTime);
|
|
44557
|
+
const currentPauseMs = this.pausedSince !== undefined ? moment__default["default"]().diff(this.pausedSince) : 0;
|
|
44558
|
+
return moment__default["default"].duration(Math.max(0, wallMs - this.pausedMs - currentPauseMs));
|
|
44559
|
+
}
|
|
44560
|
+
}
|
|
44561
|
+
|
|
44562
|
+
/**
|
|
44563
|
+
* Refresh interval for the progress header in milliseconds.
|
|
44564
|
+
*/
|
|
44565
|
+
const PROGRESS_REFRESH_INTERVAL_MS = 1000;
|
|
44566
|
+
/**
|
|
44567
|
+
* Number of terminal lines reserved for the sticky progress header.
|
|
44568
|
+
*/
|
|
44569
|
+
const PROGRESS_HEADER_RESERVED_LINES = 3;
|
|
44427
44570
|
/**
|
|
44428
44571
|
* Compact CLI progress display that stays pinned at the top of the terminal.
|
|
44429
44572
|
*/
|
|
@@ -44431,11 +44574,12 @@
|
|
|
44431
44574
|
/**
|
|
44432
44575
|
* Creates a new display that uses the provided start time when computing estimates.
|
|
44433
44576
|
*/
|
|
44434
|
-
constructor(startTime) {
|
|
44435
|
-
this.
|
|
44577
|
+
constructor(startTime, minimumPriority) {
|
|
44578
|
+
this.minimumPriority = minimumPriority;
|
|
44436
44579
|
this.stats = { done: 0, forAgent: 0, belowMinimumPriority: 0, toBeWritten: 0 };
|
|
44437
44580
|
this.isHeaderReserved = false;
|
|
44438
44581
|
this.isInteractive = Boolean(process.stdout.isTTY);
|
|
44582
|
+
this.timer = new CoderRunTimer(startTime);
|
|
44439
44583
|
if (!this.isInteractive) {
|
|
44440
44584
|
return;
|
|
44441
44585
|
}
|
|
@@ -44454,6 +44598,20 @@
|
|
|
44454
44598
|
this.stats = stats;
|
|
44455
44599
|
this.render();
|
|
44456
44600
|
}
|
|
44601
|
+
/**
|
|
44602
|
+
* Pauses the active timer while the runner is waiting for user input.
|
|
44603
|
+
*/
|
|
44604
|
+
pauseTimer() {
|
|
44605
|
+
this.timer.pause();
|
|
44606
|
+
this.render();
|
|
44607
|
+
}
|
|
44608
|
+
/**
|
|
44609
|
+
* Resumes the active timer after a pause.
|
|
44610
|
+
*/
|
|
44611
|
+
resumeTimer() {
|
|
44612
|
+
this.timer.resume();
|
|
44613
|
+
this.render();
|
|
44614
|
+
}
|
|
44457
44615
|
/**
|
|
44458
44616
|
* Stops the automatic refresh cycle and renders the final header once more.
|
|
44459
44617
|
*/
|
|
@@ -44471,14 +44629,17 @@
|
|
|
44471
44629
|
* Repaint the header without disturbing the current cursor position.
|
|
44472
44630
|
*/
|
|
44473
44631
|
render() {
|
|
44632
|
+
var _a;
|
|
44474
44633
|
if (!this.isInteractive) {
|
|
44475
44634
|
return;
|
|
44476
44635
|
}
|
|
44477
|
-
const
|
|
44636
|
+
const lines = this.buildProgressLines();
|
|
44478
44637
|
process.stdout.write('\x1b[s');
|
|
44479
|
-
|
|
44480
|
-
|
|
44481
|
-
|
|
44638
|
+
for (let lineIndex = 0; lineIndex < PROGRESS_HEADER_RESERVED_LINES; lineIndex++) {
|
|
44639
|
+
readline.cursorTo(process.stdout, 0, lineIndex);
|
|
44640
|
+
readline.clearLine(process.stdout, 0);
|
|
44641
|
+
process.stdout.write((_a = lines[lineIndex]) !== null && _a !== void 0 ? _a : '');
|
|
44642
|
+
}
|
|
44482
44643
|
process.stdout.write('\x1b[u');
|
|
44483
44644
|
}
|
|
44484
44645
|
/**
|
|
@@ -44492,72 +44653,74 @@
|
|
|
44492
44653
|
this.isHeaderReserved = true;
|
|
44493
44654
|
}
|
|
44494
44655
|
/**
|
|
44495
|
-
* Builds the
|
|
44656
|
+
* Builds the colored progress text padded to the terminal width.
|
|
44496
44657
|
*/
|
|
44497
|
-
|
|
44658
|
+
buildProgressLines() {
|
|
44498
44659
|
var _a, _b;
|
|
44499
|
-
const snapshot =
|
|
44500
|
-
const
|
|
44501
|
-
const
|
|
44502
|
-
|
|
44503
|
-
|
|
44504
|
-
|
|
44505
|
-
|
|
44660
|
+
const snapshot = buildCoderRunProgressSnapshot(this.stats, this.timer.getElapsedDuration(), (_a = this.initialDone) !== null && _a !== void 0 ? _a : this.stats.done);
|
|
44661
|
+
const columns = Math.max(40, (_b = process.stdout.columns) !== null && _b !== void 0 ? _b : 80);
|
|
44662
|
+
const workingLine = snapshot.sessionTotal > 0
|
|
44663
|
+
? [
|
|
44664
|
+
`Working on ${snapshot.currentPromptIndex}/${snapshot.sessionTotal} prompts`,
|
|
44665
|
+
`Priority >=${this.minimumPriority}`,
|
|
44666
|
+
`Repo total ${snapshot.totalPrompts}`,
|
|
44667
|
+
].join(' | ')
|
|
44668
|
+
: [`No runnable prompts`, `Priority >=${this.minimumPriority}`, `Repo total ${snapshot.totalPrompts}`].join(' | ');
|
|
44669
|
+
const detailParts = [
|
|
44670
|
+
`Done ${snapshot.sessionDone}/${snapshot.sessionTotal} this run`,
|
|
44671
|
+
`Elapsed ${snapshot.elapsedText} / ${snapshot.estimatedTotalText}`,
|
|
44672
|
+
`Est. done ${snapshot.estimatedLabel}`,
|
|
44673
|
+
];
|
|
44674
|
+
if (snapshot.skippedPrompts > 0) {
|
|
44675
|
+
detailParts.splice(1, 0, `Skipping ${snapshot.skippedPrompts} prompts with Priority <${this.minimumPriority}`);
|
|
44676
|
+
}
|
|
44677
|
+
if (snapshot.toBeWrittenPrompts > 0) {
|
|
44678
|
+
detailParts.splice(detailParts.length - 2, 0, `Write first ${formatPromptCount$1(snapshot.toBeWrittenPrompts)}`);
|
|
44679
|
+
}
|
|
44680
|
+
const progressLabel = `${snapshot.percentage}% complete (${snapshot.sessionDone}/${snapshot.sessionTotal} done)`;
|
|
44681
|
+
const progressBar = buildProgressBar$1(snapshot.percentage, progressLabel, columns);
|
|
44682
|
+
return [
|
|
44683
|
+
colors__default["default"].bgCyan.black(padPlainText(workingLine, columns)),
|
|
44684
|
+
colors__default["default"].bgBlack.white(padPlainText(detailParts.join(' | '), columns)),
|
|
44685
|
+
colors__default["default"].bgBlack(progressBar),
|
|
44686
|
+
];
|
|
44506
44687
|
}
|
|
44507
44688
|
}
|
|
44508
44689
|
/**
|
|
44509
|
-
*
|
|
44690
|
+
* Builds a colored progress bar with an explicit completion label.
|
|
44510
44691
|
*/
|
|
44511
|
-
function
|
|
44512
|
-
const
|
|
44513
|
-
const
|
|
44514
|
-
const
|
|
44515
|
-
const
|
|
44516
|
-
|
|
44517
|
-
const elapsedDuration = moment__default["default"].duration(moment__default["default"]().diff(startTime));
|
|
44518
|
-
const elapsedText = formatDurationBrief$1(elapsedDuration);
|
|
44519
|
-
let estimatedTotalText = '—';
|
|
44520
|
-
let estimatedLabel = 'unknown';
|
|
44521
|
-
if (totalPrompts > 0 && completedPrompts > 0) {
|
|
44522
|
-
const estimatedTotalMs = (elapsedDuration.asMilliseconds() * totalPrompts) / completedPrompts;
|
|
44523
|
-
const estimatedTotalDuration = moment__default["default"].duration(estimatedTotalMs);
|
|
44524
|
-
const estimatedCompletion = startTime.clone().add(estimatedTotalDuration);
|
|
44525
|
-
estimatedTotalText = formatDurationBrief$1(estimatedTotalDuration);
|
|
44526
|
-
estimatedLabel = estimatedCompletion.calendar(null, ESTIMATED_DONE_CALENDAR_FORMATS$1);
|
|
44527
|
-
}
|
|
44528
|
-
return {
|
|
44529
|
-
totalPrompts,
|
|
44530
|
-
completedPrompts,
|
|
44531
|
-
sessionDone,
|
|
44532
|
-
sessionTotal,
|
|
44533
|
-
percentage,
|
|
44534
|
-
elapsedText,
|
|
44535
|
-
estimatedTotalText,
|
|
44536
|
-
estimatedLabel,
|
|
44537
|
-
};
|
|
44692
|
+
function buildProgressBar$1(percentage, label, width) {
|
|
44693
|
+
const safeLabel = ` ${label}`;
|
|
44694
|
+
const barWidth = Math.max(10, width - safeLabel.length);
|
|
44695
|
+
const filledWidth = Math.round((percentage / 100) * barWidth);
|
|
44696
|
+
const emptyWidth = Math.max(0, barWidth - filledWidth);
|
|
44697
|
+
return `${colors__default["default"].green('█'.repeat(filledWidth))}${colors__default["default"].gray('░'.repeat(emptyWidth))}${safeLabel}`;
|
|
44538
44698
|
}
|
|
44539
44699
|
/**
|
|
44540
|
-
*
|
|
44700
|
+
* Pads or truncates one plain-text header line to the terminal width.
|
|
44541
44701
|
*/
|
|
44542
|
-
function
|
|
44543
|
-
|
|
44544
|
-
|
|
44545
|
-
|
|
44546
|
-
|
|
44547
|
-
|
|
44548
|
-
if (hours > 0) {
|
|
44549
|
-
parts.push(`${hours}h`);
|
|
44550
|
-
}
|
|
44551
|
-
if (minutes > 0) {
|
|
44552
|
-
parts.push(`${minutes}m`);
|
|
44553
|
-
}
|
|
44554
|
-
if (!parts.length && seconds > 0) {
|
|
44555
|
-
parts.push(`${seconds}s`);
|
|
44556
|
-
}
|
|
44557
|
-
if (!parts.length) {
|
|
44558
|
-
parts.push('0s');
|
|
44702
|
+
function padPlainText(text, width) {
|
|
44703
|
+
if (text.length > width) {
|
|
44704
|
+
if (width <= 3) {
|
|
44705
|
+
return '.'.repeat(width);
|
|
44706
|
+
}
|
|
44707
|
+
return `${text.slice(0, width - 3)}...`;
|
|
44559
44708
|
}
|
|
44560
|
-
return
|
|
44709
|
+
return text.padEnd(width);
|
|
44710
|
+
}
|
|
44711
|
+
/**
|
|
44712
|
+
* Formats a prompt count with the correct singular/plural noun.
|
|
44713
|
+
*/
|
|
44714
|
+
function formatPromptCount$1(count) {
|
|
44715
|
+
return `${count} prompt${count === 1 ? '' : 's'}`;
|
|
44716
|
+
}
|
|
44717
|
+
|
|
44718
|
+
/**
|
|
44719
|
+
* Formats commit message lines for console display.
|
|
44720
|
+
*/
|
|
44721
|
+
function formatCommitMessageForDisplay(message) {
|
|
44722
|
+
const lines = message.split(/\r?\n/);
|
|
44723
|
+
return lines.map((line) => colors__default["default"].bgBlue.white(` ${line} `)).join('\n');
|
|
44561
44724
|
}
|
|
44562
44725
|
|
|
44563
44726
|
/**
|
|
@@ -44771,14 +44934,6 @@
|
|
|
44771
44934
|
return normalized.subarray(0, writeIndex);
|
|
44772
44935
|
}
|
|
44773
44936
|
|
|
44774
|
-
/**
|
|
44775
|
-
* Formats commit message lines for console display.
|
|
44776
|
-
*/
|
|
44777
|
-
function formatCommitMessageForDisplay(message) {
|
|
44778
|
-
const lines = message.split(/\r?\n/);
|
|
44779
|
-
return lines.map((line) => colors__default["default"].bgBlue.white(` ${line} `)).join('\n');
|
|
44780
|
-
}
|
|
44781
|
-
|
|
44782
44937
|
/**
|
|
44783
44938
|
* Prints the formatted commit message preview.
|
|
44784
44939
|
*/
|
|
@@ -44824,82 +44979,36 @@
|
|
|
44824
44979
|
}
|
|
44825
44980
|
|
|
44826
44981
|
/**
|
|
44827
|
-
*
|
|
44982
|
+
* Decides whether one temporary prompt artifact should be deleted after a round finishes.
|
|
44983
|
+
*/
|
|
44984
|
+
function shouldDeleteTemporaryArtifact({ preserveArtifactsOnSuccess, hasFailed, }) {
|
|
44985
|
+
return !preserveArtifactsOnSuccess && !hasFailed;
|
|
44986
|
+
}
|
|
44987
|
+
|
|
44988
|
+
/**
|
|
44989
|
+
* Runs one prompt-processing round with a dedicated temporary runtime log file that is cleaned up only after successful non-preserved runs.
|
|
44828
44990
|
*/
|
|
44829
|
-
async function withPromptRuntimeLog(scriptPath, handler,
|
|
44991
|
+
async function withPromptRuntimeLog(scriptPath, handler, options) {
|
|
44830
44992
|
const logPath = buildScriptLogPath(scriptPath);
|
|
44993
|
+
let hasFailed = false;
|
|
44831
44994
|
await promises.unlink(logPath).catch(() => undefined);
|
|
44832
|
-
promptRoundArtifacts === null || promptRoundArtifacts === void 0 ? void 0 : promptRoundArtifacts.track(logPath, 'runtime-log');
|
|
44833
44995
|
try {
|
|
44834
44996
|
return await handler(logPath);
|
|
44835
44997
|
}
|
|
44998
|
+
catch (error) {
|
|
44999
|
+
hasFailed = true;
|
|
45000
|
+
throw error;
|
|
45001
|
+
}
|
|
44836
45002
|
finally {
|
|
44837
|
-
if (
|
|
45003
|
+
if (shouldDeleteTemporaryArtifact({
|
|
45004
|
+
preserveArtifactsOnSuccess: options === null || options === void 0 ? void 0 : options.preserveArtifactsOnSuccess,
|
|
45005
|
+
hasFailed,
|
|
45006
|
+
})) {
|
|
44838
45007
|
await promises.unlink(logPath).catch(() => undefined);
|
|
44839
45008
|
}
|
|
44840
45009
|
}
|
|
44841
45010
|
}
|
|
44842
45011
|
|
|
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
|
-
|
|
44903
45012
|
/**
|
|
44904
45013
|
* Waits for the user to press Enter before continuing.
|
|
44905
45014
|
*/
|
|
@@ -46739,6 +46848,15 @@
|
|
|
46739
46848
|
return `${path.relative(process.cwd(), file.path).replace(/\\/g, '/')}#${section.startLine + 1}`;
|
|
46740
46849
|
}
|
|
46741
46850
|
|
|
46851
|
+
/**
|
|
46852
|
+
* Extracts a short summary line from a prompt section.
|
|
46853
|
+
*/
|
|
46854
|
+
function buildPromptSummary(file, section) {
|
|
46855
|
+
const lines = buildCodexPrompt(file, section).split(/\r?\n/);
|
|
46856
|
+
const firstLine = lines.find((line) => line.trim() !== '');
|
|
46857
|
+
return (firstLine === null || firstLine === void 0 ? void 0 : firstLine.trim()) || '(empty prompt)';
|
|
46858
|
+
}
|
|
46859
|
+
|
|
46742
46860
|
/**
|
|
46743
46861
|
* Builds the script path for a prompt section.
|
|
46744
46862
|
*/
|
|
@@ -46798,15 +46916,6 @@
|
|
|
46798
46916
|
return nextPrompt;
|
|
46799
46917
|
}
|
|
46800
46918
|
|
|
46801
|
-
/**
|
|
46802
|
-
* Extracts a short summary line from a prompt section.
|
|
46803
|
-
*/
|
|
46804
|
-
function buildPromptSummary(file, section) {
|
|
46805
|
-
const lines = buildCodexPrompt(file, section).split(/\r?\n/);
|
|
46806
|
-
const firstLine = lines.find((line) => line.trim() !== '');
|
|
46807
|
-
return (firstLine === null || firstLine === void 0 ? void 0 : firstLine.trim()) || '(empty prompt)';
|
|
46808
|
-
}
|
|
46809
|
-
|
|
46810
46919
|
/**
|
|
46811
46920
|
* Lists upcoming tasks that are ready to run (no authoring placeholders).
|
|
46812
46921
|
*/
|
|
@@ -47358,25 +47467,29 @@ bash "$1"
|
|
|
47358
47467
|
}
|
|
47359
47468
|
|
|
47360
47469
|
/**
|
|
47361
|
-
* Creates a temporary script file, runs a handler, and
|
|
47470
|
+
* Creates a temporary script file, runs a handler, and cleans it up unless preservation is requested or the run fails.
|
|
47362
47471
|
*/
|
|
47363
47472
|
async function withTempScript(options, handler) {
|
|
47364
|
-
const { scriptPath, scriptContent
|
|
47473
|
+
const { scriptPath, scriptContent } = options;
|
|
47474
|
+
let hasFailed = false;
|
|
47365
47475
|
await promises.mkdir(posix.dirname(scriptPath), { recursive: true });
|
|
47366
47476
|
await promises.writeFile(scriptPath, scriptContent, 'utf-8');
|
|
47367
|
-
promptRoundArtifacts === null || promptRoundArtifacts === void 0 ? void 0 : promptRoundArtifacts.track(scriptPath, getPromptRoundArtifactKindFromScriptPath(scriptPath));
|
|
47368
47477
|
try {
|
|
47369
47478
|
return await handler(scriptPath);
|
|
47370
47479
|
}
|
|
47480
|
+
catch (error) {
|
|
47481
|
+
hasFailed = true;
|
|
47482
|
+
throw error;
|
|
47483
|
+
}
|
|
47371
47484
|
finally {
|
|
47372
|
-
if (
|
|
47485
|
+
if (shouldDeleteTemporaryArtifact({ preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess, hasFailed })) {
|
|
47373
47486
|
await promises.unlink(scriptPath).catch(() => undefined);
|
|
47374
47487
|
}
|
|
47375
47488
|
}
|
|
47376
47489
|
}
|
|
47377
47490
|
|
|
47378
47491
|
/**
|
|
47379
|
-
* Creates a temporary script file, runs it, captures output, and cleans it up
|
|
47492
|
+
* Creates a temporary script file, runs it, captures output, and cleans it up unless preservation is requested or the run fails.
|
|
47380
47493
|
*/
|
|
47381
47494
|
async function $runGoScriptWithOutput(options) {
|
|
47382
47495
|
return await withTempScript(options, async (scriptPath) => {
|
|
@@ -47479,7 +47592,7 @@ bash "$1"
|
|
|
47479
47592
|
scriptPath: options.scriptPath,
|
|
47480
47593
|
scriptContent,
|
|
47481
47594
|
logPath: options.logPath,
|
|
47482
|
-
|
|
47595
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
47483
47596
|
});
|
|
47484
47597
|
const usage = parseClaudeCodeJsonOutput(output);
|
|
47485
47598
|
return { usage };
|
|
@@ -47487,7 +47600,7 @@ bash "$1"
|
|
|
47487
47600
|
}
|
|
47488
47601
|
|
|
47489
47602
|
/**
|
|
47490
|
-
* Creates a temporary script file, runs it, and cleans it up
|
|
47603
|
+
* Creates a temporary script file, runs it, and cleans it up unless preservation is requested or the run fails.
|
|
47491
47604
|
*/
|
|
47492
47605
|
async function $runGoScript(options) {
|
|
47493
47606
|
await withTempScript(options, async (scriptPath) => {
|
|
@@ -47543,7 +47656,7 @@ bash "$1"
|
|
|
47543
47656
|
scriptPath: options.scriptPath,
|
|
47544
47657
|
scriptContent,
|
|
47545
47658
|
logPath: options.logPath,
|
|
47546
|
-
|
|
47659
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
47547
47660
|
});
|
|
47548
47661
|
return { usage: UNCERTAIN_USAGE };
|
|
47549
47662
|
}
|
|
@@ -47668,7 +47781,7 @@ bash "$1"
|
|
|
47668
47781
|
scriptPath: options.scriptPath,
|
|
47669
47782
|
scriptContent,
|
|
47670
47783
|
logPath: options.logPath,
|
|
47671
|
-
|
|
47784
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
47672
47785
|
});
|
|
47673
47786
|
const usage = parseGeminiUsageFromOutput(output, options.prompt, this.options.model);
|
|
47674
47787
|
return { usage };
|
|
@@ -47725,7 +47838,7 @@ bash "$1"
|
|
|
47725
47838
|
scriptPath: options.scriptPath,
|
|
47726
47839
|
scriptContent,
|
|
47727
47840
|
logPath: options.logPath,
|
|
47728
|
-
|
|
47841
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
47729
47842
|
});
|
|
47730
47843
|
return { usage: UNCERTAIN_USAGE };
|
|
47731
47844
|
}
|
|
@@ -47901,7 +48014,7 @@ bash "$1"
|
|
|
47901
48014
|
}
|
|
47902
48015
|
|
|
47903
48016
|
/**
|
|
47904
|
-
* Creates a temporary script file, runs it, waits for a completion marker and idle time, and
|
|
48017
|
+
* Creates a temporary script file, runs it, waits for a completion marker and idle time, and cleans it up unless preservation is requested or the run fails.
|
|
47905
48018
|
* Returns the captured output for post-processing.
|
|
47906
48019
|
*/
|
|
47907
48020
|
async function $runGoScriptUntilMarkerIdle(options) {
|
|
@@ -48290,7 +48403,7 @@ bash "$1"
|
|
|
48290
48403
|
completionLineMatcher: CODEX_COMPLETION_LINE,
|
|
48291
48404
|
idleTimeoutMs: CODEX_COMPLETION_IDLE_MS,
|
|
48292
48405
|
logPath: options.logPath,
|
|
48293
|
-
|
|
48406
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
48294
48407
|
});
|
|
48295
48408
|
this.rateLimitBackoff.reset();
|
|
48296
48409
|
return { usage: buildCodexUsageFromOutput(output, this.options.model) };
|
|
@@ -48425,7 +48538,7 @@ bash "$1"
|
|
|
48425
48538
|
scriptPath: options.scriptPath,
|
|
48426
48539
|
scriptContent,
|
|
48427
48540
|
logPath: options.logPath,
|
|
48428
|
-
|
|
48541
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
48429
48542
|
});
|
|
48430
48543
|
}
|
|
48431
48544
|
catch (error) {
|
|
@@ -48453,6 +48566,7 @@ bash "$1"
|
|
|
48453
48566
|
${options.command}
|
|
48454
48567
|
`),
|
|
48455
48568
|
logPath: options.logPath,
|
|
48569
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
48456
48570
|
});
|
|
48457
48571
|
}
|
|
48458
48572
|
|
|
@@ -48477,7 +48591,7 @@ bash "$1"
|
|
|
48477
48591
|
scriptPath: options.scriptPath,
|
|
48478
48592
|
projectPath: options.projectPath,
|
|
48479
48593
|
logPath: options.logPath,
|
|
48480
|
-
|
|
48594
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
48481
48595
|
});
|
|
48482
48596
|
return { ...result, attemptCount: 1 };
|
|
48483
48597
|
}
|
|
@@ -48490,7 +48604,7 @@ bash "$1"
|
|
|
48490
48604
|
scriptPath: options.scriptPath,
|
|
48491
48605
|
projectPath: options.projectPath,
|
|
48492
48606
|
logPath: options.logPath,
|
|
48493
|
-
|
|
48607
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
48494
48608
|
});
|
|
48495
48609
|
console.info(colors__default["default"].gray(`Running verification command after attempt #${attemptCount}: ${normalizedTestCommand}`));
|
|
48496
48610
|
try {
|
|
@@ -48499,6 +48613,7 @@ bash "$1"
|
|
|
48499
48613
|
projectPath: options.projectPath,
|
|
48500
48614
|
scriptPath: buildPromptTestScriptPath(options.scriptPath),
|
|
48501
48615
|
logPath: options.logPath,
|
|
48616
|
+
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
48502
48617
|
});
|
|
48503
48618
|
return { ...result, attemptCount };
|
|
48504
48619
|
}
|
|
@@ -48580,24 +48695,203 @@ bash "$1"
|
|
|
48580
48695
|
}
|
|
48581
48696
|
|
|
48582
48697
|
/**
|
|
48583
|
-
* Maximum number of
|
|
48584
|
-
*
|
|
48585
|
-
* @private internal constant of coder run UI
|
|
48698
|
+
* Maximum number of output lines reserved for agent output in the UI.
|
|
48586
48699
|
*/
|
|
48587
|
-
const
|
|
48700
|
+
const MAX_VISIBLE_OUTPUT_LINES = 8;
|
|
48588
48701
|
/**
|
|
48589
|
-
*
|
|
48702
|
+
* Builds the complete boxed terminal frame for the rich `ptbk coder run` UI.
|
|
48703
|
+
*/
|
|
48704
|
+
function buildCoderRunUiFrame(options) {
|
|
48705
|
+
const totalWidth = Math.max(56, Math.min(options.terminalWidth, 96));
|
|
48706
|
+
const isPromptActive = options.phase === 'running' || options.phase === 'verifying' || options.phase === 'loading';
|
|
48707
|
+
const promptStatusPrefix = isPromptActive ? `${colors__default["default"].yellow(`${options.spinner} `)}` : '';
|
|
48708
|
+
const sessionScopeLine = options.progress.sessionTotal > 0
|
|
48709
|
+
? `Working on ${options.progress.currentPromptIndex}/${options.progress.sessionTotal} prompts with Priority ≥${options.config.priority}`
|
|
48710
|
+
: `No runnable prompts with Priority ≥${options.config.priority}`;
|
|
48711
|
+
const sessionCountLine = `Done ${options.progress.sessionDone}/${options.progress.sessionTotal} this run · Repo total ${options.progress.totalPrompts}`;
|
|
48712
|
+
const sessionQueueParts = [];
|
|
48713
|
+
if (options.progress.skippedPrompts > 0) {
|
|
48714
|
+
sessionQueueParts.push(`Skipping ${formatPromptCount(options.progress.skippedPrompts)} with Priority <${options.config.priority}`);
|
|
48715
|
+
}
|
|
48716
|
+
if (options.progress.toBeWrittenPrompts > 0) {
|
|
48717
|
+
sessionQueueParts.push(`Write first ${formatPromptCount(options.progress.toBeWrittenPrompts)}`);
|
|
48718
|
+
}
|
|
48719
|
+
const sessionLines = [
|
|
48720
|
+
`${buildPhaseBadge(options.phase, options.pauseState)} ${fitPlainText(options.statusMessage, totalWidth - 18)}`,
|
|
48721
|
+
sessionScopeLine,
|
|
48722
|
+
sessionCountLine,
|
|
48723
|
+
...(sessionQueueParts.length > 0 ? [sessionQueueParts.join(' · ')] : []),
|
|
48724
|
+
`Elapsed ${options.progress.elapsedText} · Est. total ${options.progress.estimatedTotalText} · Est. done ${options.progress.estimatedLabel}`,
|
|
48725
|
+
buildProgressBar(options.progress.percentage, totalWidth - 6, `${options.progress.percentage}% complete (${options.progress.sessionDone}/${options.progress.sessionTotal} done)`),
|
|
48726
|
+
];
|
|
48727
|
+
const metadataParts = [options.config.agentName || 'No agent selected'];
|
|
48728
|
+
if (options.config.modelName) {
|
|
48729
|
+
metadataParts.push(options.config.modelName);
|
|
48730
|
+
}
|
|
48731
|
+
if (options.config.thinkingLevel) {
|
|
48732
|
+
metadataParts.push(`thinking ${options.config.thinkingLevel}`);
|
|
48733
|
+
}
|
|
48734
|
+
const runnerDetails = [
|
|
48735
|
+
[`${colors__default["default"].bgCyan.black(' PTBK ')}`, colors__default["default"].bgBlue.white(' CODER '), colors__default["default"].bold.white(' Promptbook Coder')]
|
|
48736
|
+
.join(''),
|
|
48737
|
+
metadataParts.join(' · '),
|
|
48738
|
+
buildConfigSummaryLine(options.config),
|
|
48739
|
+
];
|
|
48740
|
+
const currentTaskLines = options.currentPromptLabel
|
|
48741
|
+
? [
|
|
48742
|
+
`${promptStatusPrefix}${colors__default["default"].bold.white(fitPlainText(options.currentPromptLabel, totalWidth - 8))}`,
|
|
48743
|
+
`Attempt ${options.currentAttempt}/${options.maxAttempts} · ${options.statusMessage}`,
|
|
48744
|
+
...options.detailLines.map((detailLine) => `• ${detailLine}`),
|
|
48745
|
+
]
|
|
48746
|
+
: [options.statusMessage, ...options.detailLines.map((detailLine) => `• ${detailLine}`)];
|
|
48747
|
+
const visibleOutputLines = options.agentOutputLines.length > 0
|
|
48748
|
+
? options.agentOutputLines.slice(-MAX_VISIBLE_OUTPUT_LINES).map((line) => `› ${stripAnsi(line)}`)
|
|
48749
|
+
: ['No live agent output yet.'];
|
|
48750
|
+
const controls = buildControlPills(options.pauseState, options.pendingEnterLabel).join(' ');
|
|
48751
|
+
const frame = [
|
|
48752
|
+
...renderBox('Brand', runnerDetails, totalWidth, colors__default["default"].cyan.bold),
|
|
48753
|
+
...renderBox('Session', sessionLines, totalWidth, colors__default["default"].yellow.bold),
|
|
48754
|
+
...renderBox(options.currentPromptLabel ? 'Current task' : 'Queue', currentTaskLines, totalWidth, colors__default["default"].magenta.bold),
|
|
48755
|
+
...renderBox('Live output', visibleOutputLines, totalWidth, colors__default["default"].green.bold),
|
|
48756
|
+
];
|
|
48757
|
+
if (options.errors.length > 0) {
|
|
48758
|
+
frame.push(...renderBox('Errors', options.errors.map((errorLine) => `${colors__default["default"].red('✗')} ${errorLine}`), totalWidth, colors__default["default"].red.bold));
|
|
48759
|
+
}
|
|
48760
|
+
frame.push(...renderBox('Controls', [controls], totalWidth, colors__default["default"].white.bold));
|
|
48761
|
+
return frame;
|
|
48762
|
+
}
|
|
48763
|
+
/**
|
|
48764
|
+
* Renders a framed box with a colored title and padded body lines.
|
|
48765
|
+
*/
|
|
48766
|
+
function renderBox(title, lines, totalWidth, colorizeTitle) {
|
|
48767
|
+
const bodyWidth = Math.max(10, totalWidth - 4);
|
|
48768
|
+
const titleText = ` ${title} `;
|
|
48769
|
+
const topBorder = colors__default["default"].gray('┌') +
|
|
48770
|
+
colorizeTitle(titleText) +
|
|
48771
|
+
colors__default["default"].gray('─'.repeat(Math.max(0, totalWidth - 2 - titleText.length)) + '┐');
|
|
48772
|
+
const body = lines.map((line) => {
|
|
48773
|
+
const paddedLine = padAnsiText(line, bodyWidth);
|
|
48774
|
+
return colors__default["default"].gray('│ ') + paddedLine + colors__default["default"].gray(' │');
|
|
48775
|
+
});
|
|
48776
|
+
const bottomBorder = colors__default["default"].gray(`└${'─'.repeat(totalWidth - 2)}┘`);
|
|
48777
|
+
return [topBorder, ...body, bottomBorder];
|
|
48778
|
+
}
|
|
48779
|
+
/**
|
|
48780
|
+
* Builds the compact config summary line shown in the branding box.
|
|
48781
|
+
*/
|
|
48782
|
+
function buildConfigSummaryLine(config) {
|
|
48783
|
+
const parts = [`Priority ≥${config.priority}`];
|
|
48784
|
+
if (config.context) {
|
|
48785
|
+
parts.unshift(`Context ${config.context}`);
|
|
48786
|
+
}
|
|
48787
|
+
if (config.testCommand) {
|
|
48788
|
+
parts.push(`Test ${config.testCommand}`);
|
|
48789
|
+
}
|
|
48790
|
+
return parts.join(' · ');
|
|
48791
|
+
}
|
|
48792
|
+
/**
|
|
48793
|
+
* Builds the colored phase badge shown in the session box.
|
|
48794
|
+
*/
|
|
48795
|
+
function buildPhaseBadge(phase, pauseState) {
|
|
48796
|
+
if (pauseState !== 'RUNNING' || phase === 'paused') {
|
|
48797
|
+
return colors__default["default"].bgYellow.black(' PAUSED ');
|
|
48798
|
+
}
|
|
48799
|
+
switch (phase) {
|
|
48800
|
+
case 'loading':
|
|
48801
|
+
case 'initializing':
|
|
48802
|
+
return colors__default["default"].bgCyan.black(' LOADING ');
|
|
48803
|
+
case 'running':
|
|
48804
|
+
return colors__default["default"].bgGreen.black(' RUNNING ');
|
|
48805
|
+
case 'verifying':
|
|
48806
|
+
return colors__default["default"].bgMagenta.white(' VERIFYING ');
|
|
48807
|
+
case 'waiting':
|
|
48808
|
+
return colors__default["default"].bgBlue.white(' WAITING ');
|
|
48809
|
+
case 'done':
|
|
48810
|
+
return colors__default["default"].bgGreen.black(' DONE ');
|
|
48811
|
+
case 'error':
|
|
48812
|
+
return colors__default["default"].bgRed.white(' ERROR ');
|
|
48813
|
+
default:
|
|
48814
|
+
return colors__default["default"].bgWhite.black(' READY ');
|
|
48815
|
+
}
|
|
48816
|
+
}
|
|
48817
|
+
/**
|
|
48818
|
+
* Builds the progress bar shown in the session box.
|
|
48819
|
+
*/
|
|
48820
|
+
function buildProgressBar(percentage, availableWidth, label) {
|
|
48821
|
+
const percentageLabel = label;
|
|
48822
|
+
const barWidth = Math.max(10, availableWidth - percentageLabel.length - 1);
|
|
48823
|
+
const filledWidth = Math.round((percentage / 100) * barWidth);
|
|
48824
|
+
const emptyWidth = Math.max(0, barWidth - filledWidth);
|
|
48825
|
+
return `${colors__default["default"].green('█'.repeat(filledWidth))}${colors__default["default"].gray('░'.repeat(emptyWidth))} ${percentageLabel}`;
|
|
48826
|
+
}
|
|
48827
|
+
/**
|
|
48828
|
+
* Formats a prompt count with singular/plural wording.
|
|
48829
|
+
*/
|
|
48830
|
+
function formatPromptCount(count) {
|
|
48831
|
+
return `${count} prompt${count === 1 ? '' : 's'}`;
|
|
48832
|
+
}
|
|
48833
|
+
/**
|
|
48834
|
+
* Builds the control pills shown in the footer box.
|
|
48835
|
+
*/
|
|
48836
|
+
function buildControlPills(pauseState, pendingEnterLabel) {
|
|
48837
|
+
const pills = [];
|
|
48838
|
+
if (pendingEnterLabel) {
|
|
48839
|
+
pills.push(colors__default["default"].bgWhite.black(' ENTER ') + colors__default["default"].white(` ${pendingEnterLabel}`));
|
|
48840
|
+
}
|
|
48841
|
+
pills.push(pauseState === 'RUNNING'
|
|
48842
|
+
? colors__default["default"].bgYellow.black(' P ') + colors__default["default"].white(' Pause')
|
|
48843
|
+
: colors__default["default"].bgYellow.black(' P ') + colors__default["default"].white(' Resume'));
|
|
48844
|
+
pills.push(colors__default["default"].bgRed.white(' CTRL+C ') + colors__default["default"].white(' Exit'));
|
|
48845
|
+
return pills;
|
|
48846
|
+
}
|
|
48847
|
+
/**
|
|
48848
|
+
* Pads or truncates a possibly ANSI-colored line to the target visible width.
|
|
48849
|
+
*/
|
|
48850
|
+
function padAnsiText(text, width) {
|
|
48851
|
+
const fittedText = fitAnsiText(text, width);
|
|
48852
|
+
return fittedText + ' '.repeat(Math.max(0, width - visibleLength(fittedText)));
|
|
48853
|
+
}
|
|
48854
|
+
/**
|
|
48855
|
+
* Truncates a possibly ANSI-colored line to the target visible width.
|
|
48856
|
+
*/
|
|
48857
|
+
function fitAnsiText(text, width) {
|
|
48858
|
+
if (visibleLength(text) <= width) {
|
|
48859
|
+
return text;
|
|
48860
|
+
}
|
|
48861
|
+
return fitPlainText(stripAnsi(text), width);
|
|
48862
|
+
}
|
|
48863
|
+
/**
|
|
48864
|
+
* Truncates a plain-text line to the target width with an ellipsis.
|
|
48865
|
+
*/
|
|
48866
|
+
function fitPlainText(text, width) {
|
|
48867
|
+
if (text.length <= width) {
|
|
48868
|
+
return text;
|
|
48869
|
+
}
|
|
48870
|
+
if (width <= 3) {
|
|
48871
|
+
return '.'.repeat(width);
|
|
48872
|
+
}
|
|
48873
|
+
return `${text.slice(0, width - 3)}...`;
|
|
48874
|
+
}
|
|
48875
|
+
/**
|
|
48876
|
+
* Measures visible string width by stripping ANSI escape codes.
|
|
48877
|
+
*/
|
|
48878
|
+
function visibleLength(text) {
|
|
48879
|
+
return stripAnsi(text).length;
|
|
48880
|
+
}
|
|
48881
|
+
/**
|
|
48882
|
+
* Strips ANSI escape codes from a string.
|
|
48883
|
+
*/
|
|
48884
|
+
function stripAnsi(text) {
|
|
48885
|
+
// eslint-disable-next-line no-control-regex
|
|
48886
|
+
return text.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
48887
|
+
}
|
|
48888
|
+
|
|
48889
|
+
/**
|
|
48890
|
+
* Maximum number of agent output lines kept in the scrolling output area.
|
|
48590
48891
|
*
|
|
48591
48892
|
* @private internal constant of coder run UI
|
|
48592
48893
|
*/
|
|
48593
|
-
const
|
|
48594
|
-
sameDay: '[Today] h:mm',
|
|
48595
|
-
nextDay: '[Tomorrow] h:mm',
|
|
48596
|
-
nextWeek: 'dddd h:mm',
|
|
48597
|
-
lastDay: '[Yesterday] h:mm',
|
|
48598
|
-
lastWeek: 'dddd h:mm',
|
|
48599
|
-
sameElse: 'MMM D h:mm',
|
|
48600
|
-
};
|
|
48894
|
+
const MAX_AGENT_OUTPUT_LINES = 12;
|
|
48601
48895
|
/**
|
|
48602
48896
|
* Reactive state manager for the coder run terminal UI.
|
|
48603
48897
|
*
|
|
@@ -48613,35 +48907,27 @@ bash "$1"
|
|
|
48613
48907
|
this.currentPromptLabel = '';
|
|
48614
48908
|
this.currentAttempt = 1;
|
|
48615
48909
|
this.maxAttempts = 3;
|
|
48910
|
+
this.detailLines = [];
|
|
48616
48911
|
this.agentOutputLines = [];
|
|
48617
48912
|
this.phase = 'initializing';
|
|
48618
48913
|
this.statusMessage = 'Initializing...';
|
|
48619
48914
|
this.errors = [];
|
|
48620
48915
|
this.stats = { done: 0, forAgent: 0, belowMinimumPriority: 0, toBeWritten: 0 };
|
|
48621
|
-
|
|
48622
|
-
* Total milliseconds the timer was paused/waiting (excluded from elapsed display).
|
|
48623
|
-
*/
|
|
48624
|
-
this.pausedMs = 0;
|
|
48625
|
-
this.startTime = startTime;
|
|
48626
|
-
// Timer starts paused — callers call `resumeTimer()` when actual work begins.
|
|
48627
|
-
this.pausedSince = startTime.clone();
|
|
48916
|
+
this.timer = new CoderRunTimer(startTime, true);
|
|
48628
48917
|
}
|
|
48629
48918
|
/**
|
|
48630
48919
|
* Pauses the elapsed timer (e.g. while waiting for user input or paused state).
|
|
48631
48920
|
*/
|
|
48632
48921
|
pauseTimer() {
|
|
48633
|
-
|
|
48634
|
-
|
|
48635
|
-
}
|
|
48922
|
+
this.timer.pause();
|
|
48923
|
+
this.emitChange();
|
|
48636
48924
|
}
|
|
48637
48925
|
/**
|
|
48638
48926
|
* Resumes the elapsed timer after a pause.
|
|
48639
48927
|
*/
|
|
48640
48928
|
resumeTimer() {
|
|
48641
|
-
|
|
48642
|
-
|
|
48643
|
-
this.pausedSince = undefined;
|
|
48644
|
-
}
|
|
48929
|
+
this.timer.resume();
|
|
48930
|
+
this.emitChange();
|
|
48645
48931
|
}
|
|
48646
48932
|
/**
|
|
48647
48933
|
* Replaces the configuration shown in the UI header.
|
|
@@ -48665,41 +48951,15 @@ bash "$1"
|
|
|
48665
48951
|
*/
|
|
48666
48952
|
getProgress() {
|
|
48667
48953
|
var _a;
|
|
48668
|
-
|
|
48669
|
-
const totalPrompts = stats.done + stats.forAgent + stats.toBeWritten;
|
|
48670
|
-
const sessionDone = Math.max(0, stats.done - ((_a = this.initialDone) !== null && _a !== void 0 ? _a : stats.done));
|
|
48671
|
-
const sessionTotal = sessionDone + stats.forAgent;
|
|
48672
|
-
const percentage = totalPrompts > 0 ? Math.round((stats.done / totalPrompts) * 100) : 0;
|
|
48673
|
-
const wallMs = moment__default["default"]().diff(this.startTime);
|
|
48674
|
-
const currentPauseMs = this.pausedSince !== undefined ? moment__default["default"]().diff(this.pausedSince) : 0;
|
|
48675
|
-
const activeMs = Math.max(0, wallMs - this.pausedMs - currentPauseMs);
|
|
48676
|
-
const elapsedDuration = moment__default["default"].duration(activeMs);
|
|
48677
|
-
const elapsedText = formatDurationBrief(elapsedDuration);
|
|
48678
|
-
let estimatedTotalText = '\u2014';
|
|
48679
|
-
let estimatedLabel = 'unknown';
|
|
48680
|
-
if (totalPrompts > 0 && stats.done > 0) {
|
|
48681
|
-
const estimatedTotalMs = (elapsedDuration.asMilliseconds() * totalPrompts) / stats.done;
|
|
48682
|
-
const estimatedRemainingMs = estimatedTotalMs - elapsedDuration.asMilliseconds();
|
|
48683
|
-
const estimatedTotalDuration = moment__default["default"].duration(estimatedTotalMs);
|
|
48684
|
-
const estimatedCompletion = moment__default["default"]().add(estimatedRemainingMs, 'milliseconds');
|
|
48685
|
-
estimatedTotalText = formatDurationBrief(estimatedTotalDuration);
|
|
48686
|
-
estimatedLabel = estimatedCompletion.calendar(null, ESTIMATED_DONE_CALENDAR_FORMATS);
|
|
48687
|
-
}
|
|
48688
|
-
return {
|
|
48689
|
-
totalPrompts,
|
|
48690
|
-
sessionDone,
|
|
48691
|
-
sessionTotal,
|
|
48692
|
-
percentage,
|
|
48693
|
-
elapsedText,
|
|
48694
|
-
estimatedTotalText,
|
|
48695
|
-
estimatedLabel,
|
|
48696
|
-
};
|
|
48954
|
+
return buildCoderRunProgressSnapshot(this.stats, this.timer.getElapsedDuration(), (_a = this.initialDone) !== null && _a !== void 0 ? _a : this.stats.done);
|
|
48697
48955
|
}
|
|
48698
48956
|
/**
|
|
48699
48957
|
* Sets the label of the prompt currently being processed and resets per-prompt state.
|
|
48700
48958
|
*/
|
|
48701
48959
|
setCurrentPrompt(label) {
|
|
48702
48960
|
this.currentPromptLabel = label;
|
|
48961
|
+
this.detailLines = [];
|
|
48962
|
+
this.pendingEnterLabel = undefined;
|
|
48703
48963
|
this.agentOutputLines = [];
|
|
48704
48964
|
this.currentAttempt = 1;
|
|
48705
48965
|
this.emitChange();
|
|
@@ -48739,6 +48999,20 @@ bash "$1"
|
|
|
48739
48999
|
this.statusMessage = message;
|
|
48740
49000
|
this.emitChange();
|
|
48741
49001
|
}
|
|
49002
|
+
/**
|
|
49003
|
+
* Replaces the contextual detail lines shown beneath the current prompt status.
|
|
49004
|
+
*/
|
|
49005
|
+
setDetailLines(detailLines) {
|
|
49006
|
+
this.detailLines = detailLines.filter((detailLine) => detailLine.trim() !== '');
|
|
49007
|
+
this.emitChange();
|
|
49008
|
+
}
|
|
49009
|
+
/**
|
|
49010
|
+
* Sets or clears the Enter-key action label shown in the controls panel.
|
|
49011
|
+
*/
|
|
49012
|
+
setPendingEnterLabel(pendingEnterLabel) {
|
|
49013
|
+
this.pendingEnterLabel = pendingEnterLabel;
|
|
49014
|
+
this.emitChange();
|
|
49015
|
+
}
|
|
48742
49016
|
/**
|
|
48743
49017
|
* Appends an error message to the error list shown in the UI.
|
|
48744
49018
|
*/
|
|
@@ -48750,31 +49024,6 @@ bash "$1"
|
|
|
48750
49024
|
this.emit('change');
|
|
48751
49025
|
}
|
|
48752
49026
|
}
|
|
48753
|
-
/**
|
|
48754
|
-
* Formats a duration into a compact string such as "3h 12m" or "45s".
|
|
48755
|
-
*
|
|
48756
|
-
* @private internal utility of coder run UI
|
|
48757
|
-
*/
|
|
48758
|
-
function formatDurationBrief(duration) {
|
|
48759
|
-
const totalSeconds = Math.max(0, Math.round(duration.asSeconds()));
|
|
48760
|
-
const hours = Math.floor(totalSeconds / 3600);
|
|
48761
|
-
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
48762
|
-
const seconds = totalSeconds % 60;
|
|
48763
|
-
const parts = [];
|
|
48764
|
-
if (hours > 0) {
|
|
48765
|
-
parts.push(`${hours}h`);
|
|
48766
|
-
}
|
|
48767
|
-
if (minutes > 0) {
|
|
48768
|
-
parts.push(`${minutes}m`);
|
|
48769
|
-
}
|
|
48770
|
-
if (!parts.length && seconds > 0) {
|
|
48771
|
-
parts.push(`${seconds}s`);
|
|
48772
|
-
}
|
|
48773
|
-
if (!parts.length) {
|
|
48774
|
-
parts.push('0s');
|
|
48775
|
-
}
|
|
48776
|
-
return parts.join(' ');
|
|
48777
|
-
}
|
|
48778
49027
|
|
|
48779
49028
|
/**
|
|
48780
49029
|
* Refresh interval for the terminal UI in milliseconds.
|
|
@@ -48782,18 +49031,6 @@ bash "$1"
|
|
|
48782
49031
|
* @private internal constant of coder run UI
|
|
48783
49032
|
*/
|
|
48784
49033
|
const UI_REFRESH_INTERVAL_MS = 200;
|
|
48785
|
-
/**
|
|
48786
|
-
* Character width used for the text progress bar.
|
|
48787
|
-
*
|
|
48788
|
-
* @private internal constant of coder run UI
|
|
48789
|
-
*/
|
|
48790
|
-
const PROGRESS_BAR_WIDTH = 40;
|
|
48791
|
-
/**
|
|
48792
|
-
* Maximum number of output lines reserved for agent output in the UI.
|
|
48793
|
-
*
|
|
48794
|
-
* @private internal constant of coder run UI
|
|
48795
|
-
*/
|
|
48796
|
-
const MAX_VISIBLE_OUTPUT_LINES = 8;
|
|
48797
49034
|
/**
|
|
48798
49035
|
* Spinner animation frames.
|
|
48799
49036
|
*
|
|
@@ -48812,31 +49049,12 @@ bash "$1"
|
|
|
48812
49049
|
'\u280F',
|
|
48813
49050
|
];
|
|
48814
49051
|
/**
|
|
48815
|
-
*
|
|
48816
|
-
*
|
|
48817
|
-
* @private internal utility of coder run UI
|
|
48818
|
-
*/
|
|
48819
|
-
function stripAnsi(text) {
|
|
48820
|
-
// eslint-disable-next-line no-control-regex
|
|
48821
|
-
return text.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
48822
|
-
}
|
|
48823
|
-
/**
|
|
48824
|
-
* Returns the usable terminal width, capped at 80.
|
|
49052
|
+
* Returns the usable terminal width, capped at 96.
|
|
48825
49053
|
*
|
|
48826
49054
|
* @private internal utility of coder run UI
|
|
48827
49055
|
*/
|
|
48828
49056
|
function getTerminalWidth() {
|
|
48829
|
-
return Math.min(process.stdout.columns || 80,
|
|
48830
|
-
}
|
|
48831
|
-
/**
|
|
48832
|
-
* Builds a text progress bar string from a percentage.
|
|
48833
|
-
*
|
|
48834
|
-
* @private internal utility of coder run UI
|
|
48835
|
-
*/
|
|
48836
|
-
function buildProgressBar(percentage) {
|
|
48837
|
-
const filled = Math.round((percentage / 100) * PROGRESS_BAR_WIDTH);
|
|
48838
|
-
const empty = PROGRESS_BAR_WIDTH - filled;
|
|
48839
|
-
return colors__default["default"].green('\u2588'.repeat(filled)) + colors__default["default"].gray('\u2591'.repeat(empty)) + ` ${percentage}%`;
|
|
49057
|
+
return Math.min(process.stdout.columns || 80, 96);
|
|
48840
49058
|
}
|
|
48841
49059
|
/**
|
|
48842
49060
|
* Boots the ANSI terminal UI for `ptbk coder run`.
|
|
@@ -48857,21 +49075,20 @@ bash "$1"
|
|
|
48857
49075
|
state,
|
|
48858
49076
|
startCapturingAgentOutput: () => { },
|
|
48859
49077
|
stopCapturingAgentOutput: () => { },
|
|
49078
|
+
waitForEnter: async () => { },
|
|
48860
49079
|
cleanup: () => { },
|
|
48861
49080
|
};
|
|
48862
49081
|
}
|
|
48863
|
-
// --- Console interception ---
|
|
48864
49082
|
const originalConsoleInfo = console.info;
|
|
48865
49083
|
const originalConsoleWarn = console.warn;
|
|
48866
49084
|
const originalConsoleError = console.error;
|
|
48867
49085
|
const originalConsoleLog = console.log;
|
|
48868
49086
|
let isCapturing = false;
|
|
49087
|
+
let pendingEnterResolver;
|
|
48869
49088
|
console.info = (...args) => {
|
|
48870
49089
|
if (isCapturing) {
|
|
48871
49090
|
state.addAgentOutput(args.map(String).join(' '));
|
|
48872
49091
|
}
|
|
48873
|
-
// In UI mode, non-captured output is intentionally suppressed
|
|
48874
|
-
// so it does not interfere with the repainted frame.
|
|
48875
49092
|
};
|
|
48876
49093
|
console.warn = (...args) => {
|
|
48877
49094
|
if (isCapturing) {
|
|
@@ -48888,29 +49105,11 @@ bash "$1"
|
|
|
48888
49105
|
state.addAgentOutput(args.map(String).join(' '));
|
|
48889
49106
|
}
|
|
48890
49107
|
};
|
|
48891
|
-
// --- Keyboard input (pause) ---
|
|
48892
49108
|
const readline$1 = require('readline');
|
|
48893
49109
|
readline$1.emitKeypressEvents(process.stdin);
|
|
48894
49110
|
if (process.stdin.isTTY) {
|
|
48895
49111
|
process.stdin.setRawMode(true);
|
|
48896
49112
|
}
|
|
48897
|
-
const keypressHandler = (_str, key) => {
|
|
48898
|
-
if (key.ctrl && key.name === 'c') {
|
|
48899
|
-
cleanup();
|
|
48900
|
-
process.exit(0);
|
|
48901
|
-
}
|
|
48902
|
-
if (key.name === 'p') {
|
|
48903
|
-
const current = getPauseState();
|
|
48904
|
-
if (current === 'RUNNING') {
|
|
48905
|
-
requestPause();
|
|
48906
|
-
}
|
|
48907
|
-
else {
|
|
48908
|
-
requestResume();
|
|
48909
|
-
}
|
|
48910
|
-
}
|
|
48911
|
-
};
|
|
48912
|
-
process.stdin.on('keypress', keypressHandler);
|
|
48913
|
-
// --- Rendering ---
|
|
48914
49113
|
let spinnerFrame = 0;
|
|
48915
49114
|
let previousFrameLineCount = 0;
|
|
48916
49115
|
let isRendering = false;
|
|
@@ -48938,8 +49137,22 @@ bash "$1"
|
|
|
48938
49137
|
}
|
|
48939
49138
|
isRendering = true;
|
|
48940
49139
|
try {
|
|
48941
|
-
const lines =
|
|
48942
|
-
|
|
49140
|
+
const lines = buildCoderRunUiFrame({
|
|
49141
|
+
terminalWidth: getTerminalWidth(),
|
|
49142
|
+
spinner: SPINNER_FRAMES[spinnerFrame],
|
|
49143
|
+
pauseState: getPauseState(),
|
|
49144
|
+
config: state.config,
|
|
49145
|
+
phase: state.phase,
|
|
49146
|
+
currentPromptLabel: state.currentPromptLabel,
|
|
49147
|
+
currentAttempt: state.currentAttempt,
|
|
49148
|
+
maxAttempts: state.maxAttempts,
|
|
49149
|
+
statusMessage: state.statusMessage,
|
|
49150
|
+
detailLines: state.detailLines,
|
|
49151
|
+
pendingEnterLabel: state.pendingEnterLabel,
|
|
49152
|
+
agentOutputLines: state.agentOutputLines,
|
|
49153
|
+
errors: state.errors,
|
|
49154
|
+
progress: state.getProgress(),
|
|
49155
|
+
});
|
|
48943
49156
|
if (previousFrameLineCount > 0) {
|
|
48944
49157
|
process.stdout.write(`\x1b[${previousFrameLineCount}A`);
|
|
48945
49158
|
}
|
|
@@ -48951,14 +49164,12 @@ bash "$1"
|
|
|
48951
49164
|
process.stdout.write('\n');
|
|
48952
49165
|
}
|
|
48953
49166
|
}
|
|
48954
|
-
// Clear any leftover lines from a previous longer frame.
|
|
48955
49167
|
if (lines.length < previousFrameLineCount) {
|
|
48956
49168
|
for (let i = lines.length; i < previousFrameLineCount; i++) {
|
|
48957
49169
|
process.stdout.write('\n');
|
|
48958
49170
|
readline.clearLine(process.stdout, 0);
|
|
48959
49171
|
readline.cursorTo(process.stdout, 0);
|
|
48960
49172
|
}
|
|
48961
|
-
// Move back up to the end of the current frame.
|
|
48962
49173
|
const overshoot = previousFrameLineCount - lines.length;
|
|
48963
49174
|
if (overshoot > 0) {
|
|
48964
49175
|
process.stdout.write(`\x1b[${overshoot}A`);
|
|
@@ -48971,94 +49182,35 @@ bash "$1"
|
|
|
48971
49182
|
isRendering = false;
|
|
48972
49183
|
}
|
|
48973
49184
|
}
|
|
48974
|
-
|
|
48975
|
-
|
|
48976
|
-
|
|
48977
|
-
|
|
48978
|
-
const w = getTerminalWidth();
|
|
48979
|
-
const sep = colors__default["default"].gray('\u2500'.repeat(w - 2));
|
|
48980
|
-
const spinner = SPINNER_FRAMES[spinnerFrame];
|
|
48981
|
-
const { config, phase, currentPromptLabel, currentAttempt, maxAttempts, statusMessage, agentOutputLines, errors, } = state;
|
|
48982
|
-
const progress = state.getProgress();
|
|
48983
|
-
const isPaused = getPauseState() !== 'RUNNING';
|
|
48984
|
-
const isActive = phase === 'running' || phase === 'verifying' || phase === 'loading';
|
|
48985
|
-
const lines = [];
|
|
48986
|
-
// --- Branding ---
|
|
48987
|
-
lines.push(colors__default["default"].bold.cyan('\u2728 Promptbook Coder'));
|
|
48988
|
-
// --- Config ---
|
|
48989
|
-
let configLine1 = `Agent: ${colors__default["default"].bold.green(config.agentName)}`;
|
|
48990
|
-
if (config.modelName) {
|
|
48991
|
-
configLine1 += ` \u2502 Model: ${colors__default["default"].bold(config.modelName)}`;
|
|
48992
|
-
}
|
|
48993
|
-
if (config.thinkingLevel) {
|
|
48994
|
-
configLine1 += ` \u2502 Thinking: ${colors__default["default"].bold(config.thinkingLevel)}`;
|
|
48995
|
-
}
|
|
48996
|
-
lines.push(configLine1);
|
|
48997
|
-
let configLine2 = '';
|
|
48998
|
-
if (config.context) {
|
|
48999
|
-
configLine2 += `Context: ${colors__default["default"].yellow(config.context)} \u2502 `;
|
|
49000
|
-
}
|
|
49001
|
-
configLine2 += `Priority: \u2265${config.priority}`;
|
|
49002
|
-
if (config.testCommand) {
|
|
49003
|
-
configLine2 += ` \u2502 Test: ${colors__default["default"].gray(config.testCommand)}`;
|
|
49004
|
-
}
|
|
49005
|
-
lines.push(configLine2);
|
|
49006
|
-
// --- Separator ---
|
|
49007
|
-
lines.push(sep);
|
|
49008
|
-
// --- Progress ---
|
|
49009
|
-
const progressSummary = [
|
|
49010
|
-
`${progress.sessionDone}/${progress.sessionTotal} Prompts (${progress.totalPrompts} total)`,
|
|
49011
|
-
`${progress.elapsedText}/${progress.estimatedTotalText}`,
|
|
49012
|
-
`Est. done ${progress.estimatedLabel}`,
|
|
49013
|
-
].join(' \u2502 ');
|
|
49014
|
-
lines.push(progressSummary);
|
|
49015
|
-
lines.push(buildProgressBar(progress.percentage));
|
|
49016
|
-
// --- Separator ---
|
|
49017
|
-
lines.push(sep);
|
|
49018
|
-
// --- Current prompt ---
|
|
49019
|
-
if (currentPromptLabel) {
|
|
49020
|
-
const spinnerPrefix = isActive ? colors__default["default"].yellow(`${spinner} `) : ' ';
|
|
49021
|
-
lines.push(spinnerPrefix + colors__default["default"].bold(currentPromptLabel));
|
|
49022
|
-
lines.push(colors__default["default"].gray(`Attempt ${currentAttempt}/${maxAttempts} \u2502 ${statusMessage}`));
|
|
49185
|
+
const keypressHandler = (_str, key) => {
|
|
49186
|
+
if (key.ctrl && key.name === 'c') {
|
|
49187
|
+
cleanup();
|
|
49188
|
+
process.exit(0);
|
|
49023
49189
|
}
|
|
49024
|
-
|
|
49025
|
-
|
|
49026
|
-
|
|
49027
|
-
|
|
49028
|
-
|
|
49029
|
-
|
|
49030
|
-
|
|
49031
|
-
|
|
49032
|
-
|
|
49033
|
-
|
|
49034
|
-
|
|
49035
|
-
|
|
49036
|
-
|
|
49037
|
-
|
|
49038
|
-
}
|
|
49039
|
-
|
|
49040
|
-
|
|
49041
|
-
lines.push('');
|
|
49042
|
-
for (const err of errors) {
|
|
49043
|
-
lines.push(colors__default["default"].red(`\u2717 ${err}`));
|
|
49044
|
-
}
|
|
49045
|
-
}
|
|
49046
|
-
// --- Separator ---
|
|
49047
|
-
lines.push(sep);
|
|
49048
|
-
// --- Controls ---
|
|
49049
|
-
const pauseLabel = isPaused
|
|
49050
|
-
? colors__default["default"].bgYellow.black(' PAUSED ') + colors__default["default"].gray(' [P] Resume \u2502 Ctrl+C Exit')
|
|
49051
|
-
: colors__default["default"].gray('[P] Pause \u2502 Ctrl+C Exit');
|
|
49052
|
-
lines.push(pauseLabel);
|
|
49053
|
-
return lines;
|
|
49054
|
-
}
|
|
49055
|
-
// Initial render.
|
|
49190
|
+
if (key.name === 'p') {
|
|
49191
|
+
if (getPauseState() === 'RUNNING') {
|
|
49192
|
+
requestPause();
|
|
49193
|
+
}
|
|
49194
|
+
else {
|
|
49195
|
+
requestResume();
|
|
49196
|
+
}
|
|
49197
|
+
return;
|
|
49198
|
+
}
|
|
49199
|
+
if ((key.name === 'return' || key.name === 'enter') && pendingEnterResolver) {
|
|
49200
|
+
const resolvePendingEnter = pendingEnterResolver;
|
|
49201
|
+
pendingEnterResolver = undefined;
|
|
49202
|
+
state.setPendingEnterLabel(undefined);
|
|
49203
|
+
resolvePendingEnter();
|
|
49204
|
+
}
|
|
49205
|
+
};
|
|
49206
|
+
process.stdin.on('keypress', keypressHandler);
|
|
49056
49207
|
process.stdout.write('\n');
|
|
49057
49208
|
render();
|
|
49058
49209
|
const interval = setInterval(scheduleRender, UI_REFRESH_INTERVAL_MS);
|
|
49059
|
-
// Listen for state changes and schedule a re-render (debounced).
|
|
49060
49210
|
state.on('change', scheduleRender);
|
|
49061
|
-
|
|
49211
|
+
/**
|
|
49212
|
+
* Tears down the terminal UI and restores console / stdin state.
|
|
49213
|
+
*/
|
|
49062
49214
|
function cleanup() {
|
|
49063
49215
|
clearInterval(interval);
|
|
49064
49216
|
state.off('change', scheduleRender);
|
|
@@ -49066,12 +49218,14 @@ bash "$1"
|
|
|
49066
49218
|
if (process.stdin.isTTY) {
|
|
49067
49219
|
process.stdin.setRawMode(false);
|
|
49068
49220
|
}
|
|
49221
|
+
const resolvePendingEnter = pendingEnterResolver;
|
|
49222
|
+
pendingEnterResolver = undefined;
|
|
49223
|
+
resolvePendingEnter === null || resolvePendingEnter === void 0 ? void 0 : resolvePendingEnter();
|
|
49069
49224
|
isCapturing = false;
|
|
49070
49225
|
console.info = originalConsoleInfo;
|
|
49071
49226
|
console.warn = originalConsoleWarn;
|
|
49072
49227
|
console.error = originalConsoleError;
|
|
49073
49228
|
console.log = originalConsoleLog;
|
|
49074
|
-
// Render one final frame so the user sees the last state.
|
|
49075
49229
|
render();
|
|
49076
49230
|
process.stdout.write('\n');
|
|
49077
49231
|
}
|
|
@@ -49083,6 +49237,19 @@ bash "$1"
|
|
|
49083
49237
|
stopCapturingAgentOutput() {
|
|
49084
49238
|
isCapturing = false;
|
|
49085
49239
|
},
|
|
49240
|
+
waitForEnter(actionLabel) {
|
|
49241
|
+
if (pendingEnterResolver) {
|
|
49242
|
+
throw new Error('Coder run UI is already waiting for Enter.');
|
|
49243
|
+
}
|
|
49244
|
+
state.setPendingEnterLabel(actionLabel);
|
|
49245
|
+
scheduleRender();
|
|
49246
|
+
return new Promise((resolve) => {
|
|
49247
|
+
pendingEnterResolver = () => {
|
|
49248
|
+
scheduleRender();
|
|
49249
|
+
resolve();
|
|
49250
|
+
};
|
|
49251
|
+
});
|
|
49252
|
+
},
|
|
49086
49253
|
cleanup,
|
|
49087
49254
|
};
|
|
49088
49255
|
}
|
|
@@ -49150,11 +49317,11 @@ bash "$1"
|
|
|
49150
49317
|
`));
|
|
49151
49318
|
}
|
|
49152
49319
|
const runStartDate = moment__default["default"]();
|
|
49153
|
-
const
|
|
49154
|
-
const progressDisplay = options.dryRun ||
|
|
49155
|
-
const uiHandle =
|
|
49320
|
+
const isRichUiEnabled = !options.dryRun && !options.noUi && Boolean(process.stdout.isTTY);
|
|
49321
|
+
const progressDisplay = options.dryRun || options.noUi || isRichUiEnabled ? undefined : new CliProgressDisplay(runStartDate, options.priority);
|
|
49322
|
+
const uiHandle = isRichUiEnabled ? renderCoderRunUi(runStartDate) : undefined;
|
|
49156
49323
|
// When the Ink UI is active it handles keyboard input itself, so skip the raw stdin listener.
|
|
49157
|
-
if (!
|
|
49324
|
+
if (!isRichUiEnabled) {
|
|
49158
49325
|
listenForPause();
|
|
49159
49326
|
}
|
|
49160
49327
|
try {
|
|
@@ -49270,17 +49437,19 @@ bash "$1"
|
|
|
49270
49437
|
let hasWaitedForStart = false;
|
|
49271
49438
|
while (just(true)) {
|
|
49272
49439
|
await checkPause({
|
|
49273
|
-
silent:
|
|
49440
|
+
silent: isRichUiEnabled,
|
|
49274
49441
|
onPaused: () => {
|
|
49442
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.pauseTimer();
|
|
49275
49443
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
49276
49444
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('paused');
|
|
49277
49445
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Paused');
|
|
49278
49446
|
},
|
|
49279
49447
|
onResumed: () => {
|
|
49448
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
|
|
49280
49449
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
49281
49450
|
},
|
|
49282
49451
|
});
|
|
49283
|
-
if (
|
|
49452
|
+
if (isRichUiEnabled) {
|
|
49284
49453
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('loading');
|
|
49285
49454
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Loading prompts...');
|
|
49286
49455
|
}
|
|
@@ -49288,17 +49457,17 @@ bash "$1"
|
|
|
49288
49457
|
const stats = summarizePrompts(promptFiles, options.priority);
|
|
49289
49458
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.update(stats);
|
|
49290
49459
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.updateProgress(stats);
|
|
49291
|
-
if (!
|
|
49460
|
+
if (!isRichUiEnabled) {
|
|
49292
49461
|
printStats(stats, options.priority);
|
|
49293
49462
|
}
|
|
49294
49463
|
const nextPrompt = findNextTodoPrompt(promptFiles, options.priority);
|
|
49295
49464
|
if (!hasShownUpcomingTasks) {
|
|
49296
|
-
if (stats.toBeWritten > 0 && !
|
|
49465
|
+
if (stats.toBeWritten > 0 && !isRichUiEnabled) {
|
|
49297
49466
|
console.info(colors__default["default"].yellow('Following prompts need to be written:'));
|
|
49298
49467
|
printPromptsToBeWritten(promptFiles, options.priority);
|
|
49299
49468
|
console.info('');
|
|
49300
49469
|
}
|
|
49301
|
-
if (!
|
|
49470
|
+
if (!isRichUiEnabled) {
|
|
49302
49471
|
printUpcomingTasks(listUpcomingTasks(promptFiles, options.priority));
|
|
49303
49472
|
}
|
|
49304
49473
|
hasShownUpcomingTasks = true;
|
|
@@ -49308,7 +49477,7 @@ bash "$1"
|
|
|
49308
49477
|
const message = 'No prompts ready for agent.';
|
|
49309
49478
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(message);
|
|
49310
49479
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('done');
|
|
49311
|
-
if (!
|
|
49480
|
+
if (!isRichUiEnabled) {
|
|
49312
49481
|
console.info(colors__default["default"].yellow(message));
|
|
49313
49482
|
}
|
|
49314
49483
|
}
|
|
@@ -49316,16 +49485,28 @@ bash "$1"
|
|
|
49316
49485
|
const message = 'All prompts are done.';
|
|
49317
49486
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(message);
|
|
49318
49487
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('done');
|
|
49319
|
-
if (!
|
|
49488
|
+
if (!isRichUiEnabled) {
|
|
49320
49489
|
console.info(colors__default["default"].green(message));
|
|
49321
49490
|
}
|
|
49322
49491
|
}
|
|
49323
49492
|
return;
|
|
49324
49493
|
}
|
|
49494
|
+
const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section);
|
|
49325
49495
|
if (options.waitForUser) {
|
|
49496
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.pauseTimer();
|
|
49326
49497
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
49327
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.
|
|
49328
|
-
|
|
49498
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentPrompt(promptLabel);
|
|
49499
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('waiting');
|
|
49500
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(hasWaitedForStart ? 'Waiting for confirmation to continue' : 'Waiting for confirmation to start');
|
|
49501
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setDetailLines([buildPromptSummary(nextPrompt.file, nextPrompt.section)]);
|
|
49502
|
+
if (isRichUiEnabled) {
|
|
49503
|
+
await (uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.waitForEnter(hasWaitedForStart ? 'Continue' : 'Start'));
|
|
49504
|
+
}
|
|
49505
|
+
else {
|
|
49506
|
+
await waitForPromptStart(nextPrompt.file, nextPrompt.section, !hasWaitedForStart);
|
|
49507
|
+
}
|
|
49508
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setDetailLines([]);
|
|
49509
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
|
|
49329
49510
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
49330
49511
|
hasWaitedForStart = true;
|
|
49331
49512
|
}
|
|
@@ -49335,9 +49516,7 @@ bash "$1"
|
|
|
49335
49516
|
const commitMessage = buildCommitMessage(nextPrompt.file, nextPrompt.section);
|
|
49336
49517
|
const codexPrompt = appendCoderContext(buildCodexPrompt(nextPrompt.file, nextPrompt.section), resolvedCoderContext);
|
|
49337
49518
|
const scriptPath = buildScriptPath(nextPrompt.file, nextPrompt.section);
|
|
49338
|
-
|
|
49339
|
-
const promptRoundArtifacts = createCoderRunPromptRoundArtifacts(options.preserveLogs);
|
|
49340
|
-
if (isUiMode) {
|
|
49519
|
+
if (isRichUiEnabled) {
|
|
49341
49520
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentPrompt(promptLabel);
|
|
49342
49521
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('running');
|
|
49343
49522
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Running');
|
|
@@ -49347,69 +49526,74 @@ bash "$1"
|
|
|
49347
49526
|
}
|
|
49348
49527
|
const promptExecutionStartedDate = moment__default["default"]();
|
|
49349
49528
|
let attemptCount = 1;
|
|
49350
|
-
let promptRoundOutcome = 'failure';
|
|
49351
49529
|
const roundChangedFilesSnapshot = options.normalizeLineEndings
|
|
49352
49530
|
? await captureChangedFilesSnapshot(process.cwd())
|
|
49353
49531
|
: undefined;
|
|
49354
|
-
|
|
49355
|
-
|
|
49356
|
-
|
|
49357
|
-
|
|
49358
|
-
|
|
49359
|
-
|
|
49360
|
-
|
|
49361
|
-
|
|
49362
|
-
|
|
49363
|
-
|
|
49364
|
-
|
|
49365
|
-
|
|
49366
|
-
|
|
49367
|
-
|
|
49368
|
-
|
|
49369
|
-
|
|
49370
|
-
|
|
49371
|
-
|
|
49372
|
-
|
|
49373
|
-
|
|
49374
|
-
|
|
49375
|
-
|
|
49376
|
-
|
|
49377
|
-
|
|
49378
|
-
|
|
49379
|
-
|
|
49380
|
-
|
|
49381
|
-
|
|
49382
|
-
|
|
49383
|
-
|
|
49532
|
+
await withPromptRuntimeLog(scriptPath, async (logPath) => {
|
|
49533
|
+
try {
|
|
49534
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
49535
|
+
const result = await runPromptWithTestFeedback({
|
|
49536
|
+
runner,
|
|
49537
|
+
prompt: codexPrompt,
|
|
49538
|
+
scriptPath,
|
|
49539
|
+
projectPath: process.cwd(),
|
|
49540
|
+
promptLabel,
|
|
49541
|
+
testCommand: options.testCommand,
|
|
49542
|
+
preserveArtifactsOnSuccess: options.preserveLogs,
|
|
49543
|
+
logPath,
|
|
49544
|
+
onAttemptStarted: (nextAttemptCount) => {
|
|
49545
|
+
attemptCount = nextAttemptCount;
|
|
49546
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(nextAttemptCount);
|
|
49547
|
+
if (nextAttemptCount > 1) {
|
|
49548
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Retrying (attempt ${nextAttemptCount})`);
|
|
49549
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('verifying');
|
|
49550
|
+
}
|
|
49551
|
+
},
|
|
49552
|
+
});
|
|
49553
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
49554
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Committing changes');
|
|
49555
|
+
markPromptDone(nextPrompt.file, nextPrompt.section, result.usage, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, result.attemptCount);
|
|
49556
|
+
await writePromptFile(nextPrompt.file);
|
|
49557
|
+
await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
|
|
49558
|
+
if (options.waitForUser) {
|
|
49559
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.pauseTimer();
|
|
49560
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
49561
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('waiting');
|
|
49562
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Review the commit preview and confirm to continue');
|
|
49563
|
+
if (isRichUiEnabled) {
|
|
49564
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setDetailLines(formatCommitMessageForDisplay(commitMessage)
|
|
49565
|
+
.split(/\r?\n/)
|
|
49566
|
+
.map((line) => line.trim()));
|
|
49567
|
+
await (uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.waitForEnter('Commit'));
|
|
49568
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setDetailLines([]);
|
|
49569
|
+
}
|
|
49570
|
+
else {
|
|
49384
49571
|
printCommitMessage(commitMessage);
|
|
49385
49572
|
await waitForEnter(colors__default["default"].bgWhite('Press Enter to commit and continue...'));
|
|
49386
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
49387
49573
|
}
|
|
49388
|
-
|
|
49389
|
-
|
|
49390
|
-
promptRoundOutcome = 'success';
|
|
49574
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
|
|
49575
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
49391
49576
|
}
|
|
49392
|
-
|
|
49393
|
-
|
|
49394
|
-
|
|
49395
|
-
|
|
49396
|
-
|
|
49397
|
-
|
|
49398
|
-
|
|
49399
|
-
|
|
49400
|
-
|
|
49401
|
-
|
|
49402
|
-
|
|
49403
|
-
|
|
49404
|
-
|
|
49405
|
-
|
|
49406
|
-
|
|
49407
|
-
}
|
|
49408
|
-
|
|
49409
|
-
|
|
49410
|
-
|
|
49411
|
-
|
|
49412
|
-
}
|
|
49577
|
+
await commitChanges(commitMessage, { autoPush: options.autoPush });
|
|
49578
|
+
await runPostPromptAutoMigrationIfEnabled(options);
|
|
49579
|
+
}
|
|
49580
|
+
catch (error) {
|
|
49581
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
49582
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('error');
|
|
49583
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(error instanceof Error ? error.message : String(error));
|
|
49584
|
+
markPromptFailed(nextPrompt.file, nextPrompt.section, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, attemptCount);
|
|
49585
|
+
await writePromptFile(nextPrompt.file);
|
|
49586
|
+
await writePromptErrorLog({
|
|
49587
|
+
file: nextPrompt.file,
|
|
49588
|
+
section: nextPrompt.section,
|
|
49589
|
+
runnerName: runnerMetadata.runnerName,
|
|
49590
|
+
modelName: runnerMetadata.modelName,
|
|
49591
|
+
error,
|
|
49592
|
+
});
|
|
49593
|
+
await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
|
|
49594
|
+
throw error;
|
|
49595
|
+
}
|
|
49596
|
+
}, { preserveArtifactsOnSuccess: options.preserveLogs });
|
|
49413
49597
|
}
|
|
49414
49598
|
}
|
|
49415
49599
|
finally {
|