@promptbook/cli 0.112.0-42 → 0.112.0-43
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/README.md +10 -3
- package/esm/index.es.js +1030 -86
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/formatUnknownErrorDetails.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/common/waitForPause.d.ts +21 -1
- package/esm/scripts/run-codex-prompts/git/commitChanges.d.ts +2 -2
- package/esm/scripts/run-codex-prompts/prompts/formatPromptAttemptMetadata.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/prompts/markPromptDone.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/prompts/markPromptFailed.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +13 -0
- package/esm/scripts/run-codex-prompts/testing/runPromptWithTestFeedback.d.ts +25 -0
- package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +112 -0
- package/esm/scripts/run-codex-prompts/ui/renderCoderRunUi.d.ts +30 -0
- package/esm/src/book-components/Chat/Chat/ChatProps.d.ts +1 -1
- package/esm/src/cli/cli-commands/coder/getTypescriptModule.d.ts +19 -0
- package/esm/src/cli/cli-commands/coder/getTypescriptModule.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/coder/mergeStringRecordJsonFile.test.d.ts +1 -0
- package/esm/src/llm-providers/agent/Agent.test.d.ts +1 -0
- package/esm/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +4 -0
- package/esm/src/llm-providers/agent/AgentOptions.d.ts +8 -0
- package/esm/src/llm-providers/agent/CreateAgentLlmExecutionToolsOptions.d.ts +9 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +3 -2
- package/umd/index.umd.js +1033 -90
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/formatUnknownErrorDetails.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/common/waitForPause.d.ts +21 -1
- package/umd/scripts/run-codex-prompts/git/commitChanges.d.ts +2 -2
- package/umd/scripts/run-codex-prompts/prompts/formatPromptAttemptMetadata.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/prompts/markPromptDone.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/prompts/markPromptFailed.d.ts +1 -1
- package/umd/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +13 -0
- package/umd/scripts/run-codex-prompts/testing/runPromptWithTestFeedback.d.ts +25 -0
- package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +112 -0
- package/umd/scripts/run-codex-prompts/ui/renderCoderRunUi.d.ts +30 -0
- package/umd/src/book-components/Chat/Chat/ChatProps.d.ts +1 -1
- package/umd/src/cli/cli-commands/coder/getTypescriptModule.d.ts +19 -0
- package/umd/src/cli/cli-commands/coder/getTypescriptModule.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/coder/mergeStringRecordJsonFile.test.d.ts +1 -0
- package/umd/src/llm-providers/agent/Agent.test.d.ts +1 -0
- package/umd/src/llm-providers/agent/AgentLlmExecutionTools.d.ts +4 -0
- package/umd/src/llm-providers/agent/AgentOptions.d.ts +8 -0
- package/umd/src/llm-providers/agent/CreateAgentLlmExecutionToolsOptions.d.ts +9 -0
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -37,6 +37,7 @@ import { spawn } from 'child_process';
|
|
|
37
37
|
import { Client } from 'pg';
|
|
38
38
|
import '@supabase/supabase-js';
|
|
39
39
|
import { dirname as dirname$1 } from 'path/posix';
|
|
40
|
+
import { EventEmitter } from 'events';
|
|
40
41
|
import { Subject, BehaviorSubject } from 'rxjs';
|
|
41
42
|
import { lookup, extension } from 'mime-types';
|
|
42
43
|
import { parse, unparse } from 'papaparse';
|
|
@@ -57,7 +58,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
57
58
|
* @generated
|
|
58
59
|
* @see https://github.com/webgptorg/promptbook
|
|
59
60
|
*/
|
|
60
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
61
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-43';
|
|
61
62
|
/**
|
|
62
63
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
63
64
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -2320,7 +2321,7 @@ function getDefaultCoderAgentCodingFileContent({ packageJsonScripts, }) {
|
|
|
2320
2321
|
'',
|
|
2321
2322
|
'## Customizing the workflow',
|
|
2322
2323
|
'- Edit `package.json` if you want `npm run coder:run` to use another coding agent, model, thinking level, context file, or wait mode.',
|
|
2323
|
-
'- Use direct CLI commands when you need one-off flags such as `--priority`, `--ignore-git-changes`, `--dry-run`, `--allow-credits`, or `--auto-migrate`.',
|
|
2324
|
+
'- Use direct CLI commands when you need one-off flags such as `--priority`, `--ignore-git-changes`, `--dry-run`, `--test`, `--allow-credits`, or `--auto-migrate`.',
|
|
2324
2325
|
'- Use `npx ptbk coder --help` and `npx ptbk coder <command> --help` for the full CLI reference.',
|
|
2325
2326
|
].join('\n');
|
|
2326
2327
|
}
|
|
@@ -2580,6 +2581,26 @@ class ParseError extends Error {
|
|
|
2580
2581
|
}
|
|
2581
2582
|
// TODO: Maybe split `ParseError` and `ApplyError`
|
|
2582
2583
|
|
|
2584
|
+
/**
|
|
2585
|
+
* Loads the TypeScript runtime used for parsing JSONC-style project files.
|
|
2586
|
+
*
|
|
2587
|
+
* @private internal utility of `coder init`
|
|
2588
|
+
*/
|
|
2589
|
+
async function getTypescriptModule() {
|
|
2590
|
+
return normalizeImportedTypescriptModule((await import('typescript')));
|
|
2591
|
+
}
|
|
2592
|
+
/**
|
|
2593
|
+
* Normalizes CommonJS-via-`default` and direct namespace imports of TypeScript.
|
|
2594
|
+
*
|
|
2595
|
+
* @private internal utility of `getTypescriptModule`
|
|
2596
|
+
*/
|
|
2597
|
+
function normalizeImportedTypescriptModule(importedTypescriptModule) {
|
|
2598
|
+
return 'parseConfigFileTextToJson' in importedTypescriptModule
|
|
2599
|
+
? importedTypescriptModule
|
|
2600
|
+
: importedTypescriptModule.default;
|
|
2601
|
+
}
|
|
2602
|
+
// Note: [🟡] Code for coder init TypeScript loading [getTypescriptModule](src/cli/cli-commands/coder/getTypescriptModule.ts) should never be published outside of `@promptbook/cli`
|
|
2603
|
+
|
|
2583
2604
|
/**
|
|
2584
2605
|
* Default indentation used when creating new JSON configuration files.
|
|
2585
2606
|
*/
|
|
@@ -2625,7 +2646,7 @@ async function parseJsonObjectFile(relativeFilePath, fileContent) {
|
|
|
2625
2646
|
if (fileContent.trim() === '') {
|
|
2626
2647
|
return {};
|
|
2627
2648
|
}
|
|
2628
|
-
const typescript = await
|
|
2649
|
+
const typescript = await getTypescriptModule();
|
|
2629
2650
|
const parsedFile = typescript.parseConfigFileTextToJson(relativeFilePath, fileContent);
|
|
2630
2651
|
if (parsedFile.error) {
|
|
2631
2652
|
throw new ParseError(spaceTrim$1(`
|
|
@@ -2983,7 +3004,9 @@ function $initializeCoderRunCommand(program) {
|
|
|
2983
3004
|
|
|
2984
3005
|
Features:
|
|
2985
3006
|
- Automatically stages and commits changes with agent identity
|
|
3007
|
+
- Optional post-commit git push with explicit --auto-push opt-in
|
|
2986
3008
|
- Supports GPG signing of commits
|
|
3009
|
+
- Optional post-prompt verification with test-feedback retries
|
|
2987
3010
|
- Progress tracking and interactive controls
|
|
2988
3011
|
- Dry-run mode to preview prompts
|
|
2989
3012
|
`));
|
|
@@ -2996,17 +3019,19 @@ function $initializeCoderRunCommand(program) {
|
|
|
2996
3019
|
Gemini examples: gemini-3-flash-preview, default
|
|
2997
3020
|
`));
|
|
2998
3021
|
command.option('--context <context-or-file>', 'Append extra instructions either inline or from a file path relative to the current project');
|
|
3022
|
+
command.option('--test <test-command...>', 'Run a verification command after each prompt; quote it when the command itself contains top-level flags');
|
|
2999
3023
|
command.addOption(new Option('--thinking-level <thinking-level>', `Set reasoning effort for supported runners (${THINKING_LEVEL_VALUES.join(', ')})`).choices([...THINKING_LEVEL_VALUES]));
|
|
3000
3024
|
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
|
|
3001
3025
|
command.option('--no-wait', 'Skip user prompts between processing');
|
|
3002
3026
|
command.option('--ignore-git-changes', 'Skip clean working tree check before running prompts', false);
|
|
3003
3027
|
command.option('--allow-credits', 'Allow OpenAI Codex runner to spend credits when rate limits are exhausted', false);
|
|
3004
3028
|
command.option('--no-normalize-line-endings', 'Disable automatic LF normalization for files changed in each coding round');
|
|
3005
|
-
command.option('--
|
|
3029
|
+
command.option('--auto-push', 'Automatically git push after each commit', false);
|
|
3006
3030
|
command.option('--auto-migrate', 'Run testing-server database migrations automatically after each successfully processed prompt');
|
|
3007
3031
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
3008
3032
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
3009
|
-
const { dryRun, agent, model, context, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits, normalizeLineEndings, autoMigrate, allowDestructiveAutoMigrate,
|
|
3033
|
+
const { dryRun, agent, model, context, test, thinkingLevel, priority, wait, ignoreGitChanges, allowCredits, normalizeLineEndings, autoMigrate, allowDestructiveAutoMigrate, autoPush, } = cliOptions;
|
|
3034
|
+
const testCommand = normalizeCommandOptionValue(test);
|
|
3010
3035
|
// Validate agent
|
|
3011
3036
|
let agentName = undefined;
|
|
3012
3037
|
if (agent) {
|
|
@@ -3035,13 +3060,14 @@ function $initializeCoderRunCommand(program) {
|
|
|
3035
3060
|
agentName,
|
|
3036
3061
|
model,
|
|
3037
3062
|
context,
|
|
3063
|
+
testCommand,
|
|
3038
3064
|
thinkingLevel,
|
|
3039
3065
|
priority,
|
|
3040
3066
|
normalizeLineEndings,
|
|
3041
3067
|
allowCredits,
|
|
3042
3068
|
autoMigrate,
|
|
3043
3069
|
allowDestructiveAutoMigrate,
|
|
3044
|
-
|
|
3070
|
+
autoPush,
|
|
3045
3071
|
};
|
|
3046
3072
|
// Note: Import the function dynamically to avoid loading heavy dependencies until needed
|
|
3047
3073
|
const { runCodexPrompts } = await Promise.resolve().then(function () { return runCodexPrompts$1; });
|
|
@@ -3070,6 +3096,19 @@ function parseIntOption(value) {
|
|
|
3070
3096
|
}
|
|
3071
3097
|
return parsed;
|
|
3072
3098
|
}
|
|
3099
|
+
/**
|
|
3100
|
+
* Joins one Commander option that may be parsed either as a single string or a variadic token array.
|
|
3101
|
+
*
|
|
3102
|
+
* @private internal utility of `coder run` command
|
|
3103
|
+
*/
|
|
3104
|
+
function normalizeCommandOptionValue(value) {
|
|
3105
|
+
if (value === undefined) {
|
|
3106
|
+
return undefined;
|
|
3107
|
+
}
|
|
3108
|
+
const parts = Array.isArray(value) ? value : [value];
|
|
3109
|
+
const normalizedValue = parts.map((part) => part.trim()).filter(Boolean).join(' ').trim();
|
|
3110
|
+
return normalizedValue === '' ? undefined : normalizedValue;
|
|
3111
|
+
}
|
|
3073
3112
|
// Note: [🟡] Code for CLI command [run](src/cli/cli-commands/coder/run.ts) should never be published outside of `@promptbook/cli`
|
|
3074
3113
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3075
3114
|
|
|
@@ -22556,6 +22595,15 @@ const teamToolFunctions = {};
|
|
|
22556
22595
|
* Map of team tool titles.
|
|
22557
22596
|
*/
|
|
22558
22597
|
const teamToolTitles = {};
|
|
22598
|
+
/**
|
|
22599
|
+
* Shared TEAM usage rules appended ahead of teammate listings.
|
|
22600
|
+
*
|
|
22601
|
+
* @private
|
|
22602
|
+
*/
|
|
22603
|
+
const TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES = [
|
|
22604
|
+
'- If a teammate is relevant to the request, consult that teammate using the matching tool.',
|
|
22605
|
+
'- Do not ask the user for information that a listed teammate can provide directly.',
|
|
22606
|
+
];
|
|
22559
22607
|
/**
|
|
22560
22608
|
* Constant for remote agents by Url.
|
|
22561
22609
|
*/
|
|
@@ -22645,12 +22693,9 @@ class TeamCommitmentDefinition extends BaseCommitmentDefinition {
|
|
|
22645
22693
|
if (updatedTools.some((tool) => tool.name === entry.toolName)) {
|
|
22646
22694
|
continue;
|
|
22647
22695
|
}
|
|
22648
|
-
const toolDescription = entry.description
|
|
22649
|
-
? `Consult teammate ${entry.teammate.label}\n${entry.description}`
|
|
22650
|
-
: `Consult teammate ${entry.teammate.label}`;
|
|
22651
22696
|
updatedTools.push({
|
|
22652
22697
|
name: entry.toolName,
|
|
22653
|
-
description:
|
|
22698
|
+
description: buildTeamToolDescription(entry),
|
|
22654
22699
|
parameters: {
|
|
22655
22700
|
type: 'object',
|
|
22656
22701
|
properties: {
|
|
@@ -22719,22 +22764,72 @@ function resolveTeamTeammateLabels(teamContent, teammates) {
|
|
|
22719
22764
|
/**
|
|
22720
22765
|
* Builds the textual TEAM section body for the final system message.
|
|
22721
22766
|
*
|
|
22722
|
-
* Each teammate is listed with its tool name
|
|
22723
|
-
* Uses `spaceTrim` to ensure consistent whitespace and indentation.
|
|
22767
|
+
* Each teammate is listed with its tool name, TEAM instructions, and optional profile hints.
|
|
22724
22768
|
*/
|
|
22725
22769
|
function buildTeamSystemMessageBody(teamEntries) {
|
|
22726
|
-
const lines =
|
|
22727
|
-
|
|
22728
|
-
|
|
22729
|
-
|
|
22730
|
-
|
|
22731
|
-
|
|
22732
|
-
|
|
22733
|
-
|
|
22734
|
-
|
|
22735
|
-
});
|
|
22770
|
+
const lines = [
|
|
22771
|
+
...TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES,
|
|
22772
|
+
'',
|
|
22773
|
+
...teamEntries.map((entry, index) => {
|
|
22774
|
+
const toolLine = `${index + 1}) ${entry.teammate.label} tool \`${entry.toolName}\``;
|
|
22775
|
+
const detailLines = collectTeamEntryDetails(entry).map(formatTeamEntryDetailLine);
|
|
22776
|
+
return [toolLine, ...detailLines].join('\n');
|
|
22777
|
+
}),
|
|
22778
|
+
];
|
|
22736
22779
|
return lines.join('\n');
|
|
22737
22780
|
}
|
|
22781
|
+
/**
|
|
22782
|
+
* Builds the model-visible description for one teammate tool.
|
|
22783
|
+
*
|
|
22784
|
+
* @private
|
|
22785
|
+
*/
|
|
22786
|
+
function buildTeamToolDescription(entry) {
|
|
22787
|
+
const detailLines = collectTeamEntryDetails(entry).map(({ label, content }) => `${label}: ${content}`);
|
|
22788
|
+
return [`Consult teammate ${entry.teammate.label}`, ...detailLines].join('\n');
|
|
22789
|
+
}
|
|
22790
|
+
/**
|
|
22791
|
+
* Collects structured teammate details that should stay visible to the model.
|
|
22792
|
+
*
|
|
22793
|
+
* @private
|
|
22794
|
+
*/
|
|
22795
|
+
function collectTeamEntryDetails(entry) {
|
|
22796
|
+
var _a;
|
|
22797
|
+
const details = [];
|
|
22798
|
+
const instructions = entry.teammate.instructions.trim();
|
|
22799
|
+
const description = ((_a = entry.description) === null || _a === void 0 ? void 0 : _a.trim()) || '';
|
|
22800
|
+
if (instructions) {
|
|
22801
|
+
details.push({
|
|
22802
|
+
label: 'TEAM instructions',
|
|
22803
|
+
content: instructions,
|
|
22804
|
+
});
|
|
22805
|
+
}
|
|
22806
|
+
if (description) {
|
|
22807
|
+
details.push({
|
|
22808
|
+
label: 'Profile',
|
|
22809
|
+
content: description,
|
|
22810
|
+
});
|
|
22811
|
+
}
|
|
22812
|
+
return details;
|
|
22813
|
+
}
|
|
22814
|
+
/**
|
|
22815
|
+
* Formats one teammate detail line for the TEAM system-message section.
|
|
22816
|
+
*
|
|
22817
|
+
* @private
|
|
22818
|
+
*/
|
|
22819
|
+
function formatTeamEntryDetailLine(detail) {
|
|
22820
|
+
return indentMultilineText(`${detail.label}: ${detail.content}`, ' ');
|
|
22821
|
+
}
|
|
22822
|
+
/**
|
|
22823
|
+
* Indents all lines of one potentially multi-line text block.
|
|
22824
|
+
*
|
|
22825
|
+
* @private
|
|
22826
|
+
*/
|
|
22827
|
+
function indentMultilineText(text, prefix) {
|
|
22828
|
+
return text
|
|
22829
|
+
.split('\n')
|
|
22830
|
+
.map((line) => `${prefix}${line}`)
|
|
22831
|
+
.join('\n');
|
|
22832
|
+
}
|
|
22738
22833
|
/**
|
|
22739
22834
|
* Registers tool function and title for a teammate tool.
|
|
22740
22835
|
*/
|
|
@@ -40907,7 +41002,7 @@ function createEmptyAgentModelRequirements() {
|
|
|
40907
41002
|
systemMessage: '',
|
|
40908
41003
|
promptSuffix: '',
|
|
40909
41004
|
// modelName: 'gpt-5',
|
|
40910
|
-
modelName: '
|
|
41005
|
+
modelName: 'gpt-5.4-mini',
|
|
40911
41006
|
temperature: 0.7,
|
|
40912
41007
|
topP: 0.9,
|
|
40913
41008
|
topK: 50,
|
|
@@ -44087,7 +44182,26 @@ var findRefactorCandidates$1 = /*#__PURE__*/Object.freeze({
|
|
|
44087
44182
|
/**
|
|
44088
44183
|
* CLI usage text for this script.
|
|
44089
44184
|
*/
|
|
44090
|
-
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--agent <agent-name>] [--model <model>] [--context <context-or-file>] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--allow-credits] [--auto-migrate] [--allow-destructive-auto-migrate] [--no-wait] [--ignore-git-changes] [--no-normalize-line-endings] [--
|
|
44185
|
+
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]';
|
|
44186
|
+
/**
|
|
44187
|
+
* Top-level flags supported by this command.
|
|
44188
|
+
*/
|
|
44189
|
+
const KNOWN_OPTION_FLAGS = new Set([
|
|
44190
|
+
'--dry-run',
|
|
44191
|
+
'--agent',
|
|
44192
|
+
'--model',
|
|
44193
|
+
'--context',
|
|
44194
|
+
'--test',
|
|
44195
|
+
'--thinking-level',
|
|
44196
|
+
'--priority',
|
|
44197
|
+
'--allow-credits',
|
|
44198
|
+
'--auto-migrate',
|
|
44199
|
+
'--allow-destructive-auto-migrate',
|
|
44200
|
+
'--no-wait',
|
|
44201
|
+
'--ignore-git-changes',
|
|
44202
|
+
'--no-normalize-line-endings',
|
|
44203
|
+
'--auto-push',
|
|
44204
|
+
]);
|
|
44091
44205
|
/**
|
|
44092
44206
|
* Parses CLI arguments into runner options.
|
|
44093
44207
|
*/
|
|
@@ -44108,6 +44222,8 @@ function parseRunOptions(args) {
|
|
|
44108
44222
|
}
|
|
44109
44223
|
const model = readOptionValue(args, '--model');
|
|
44110
44224
|
const context = readOptionValue(args, '--context');
|
|
44225
|
+
const hasTestCommandFlag = args.includes('--test');
|
|
44226
|
+
const testCommand = readVariadicOptionValue(args, '--test');
|
|
44111
44227
|
const hasThinkingLevelFlag = args.includes('--thinking-level');
|
|
44112
44228
|
const thinkingLevelValue = readOptionValue(args, '--thinking-level');
|
|
44113
44229
|
const hasPriorityFlag = args.includes('--priority');
|
|
@@ -44117,8 +44233,11 @@ function parseRunOptions(args) {
|
|
|
44117
44233
|
const allowCredits = args.includes('--allow-credits');
|
|
44118
44234
|
const autoMigrate = args.includes('--auto-migrate');
|
|
44119
44235
|
const allowDestructiveAutoMigrate = args.includes('--allow-destructive-auto-migrate');
|
|
44120
|
-
const
|
|
44236
|
+
const autoPush = args.includes('--auto-push');
|
|
44121
44237
|
let thinkingLevel;
|
|
44238
|
+
if (hasTestCommandFlag && testCommand === undefined) {
|
|
44239
|
+
exitWithUsageError('Missing value for --test. Use a shell command such as `npm run test` and quote it when it contains top-level CLI flags.');
|
|
44240
|
+
}
|
|
44122
44241
|
if (hasThinkingLevelFlag && thinkingLevelValue === undefined) {
|
|
44123
44242
|
exitWithUsageError(`Missing value for --thinking-level. Use one of: ${THINKING_LEVEL_VALUES.join(', ')}.`);
|
|
44124
44243
|
}
|
|
@@ -44139,10 +44258,11 @@ function parseRunOptions(args) {
|
|
|
44139
44258
|
allowCredits,
|
|
44140
44259
|
autoMigrate,
|
|
44141
44260
|
allowDestructiveAutoMigrate,
|
|
44142
|
-
|
|
44261
|
+
autoPush,
|
|
44143
44262
|
agentName,
|
|
44144
44263
|
model,
|
|
44145
44264
|
context,
|
|
44265
|
+
testCommand,
|
|
44146
44266
|
thinkingLevel,
|
|
44147
44267
|
priority,
|
|
44148
44268
|
};
|
|
@@ -44157,6 +44277,28 @@ function readOptionValue(args, flag) {
|
|
|
44157
44277
|
const index = args.indexOf(flag);
|
|
44158
44278
|
return args[index + 1];
|
|
44159
44279
|
}
|
|
44280
|
+
/**
|
|
44281
|
+
* Reads a multi-token shell command value that follows a given flag.
|
|
44282
|
+
*/
|
|
44283
|
+
function readVariadicOptionValue(args, flag) {
|
|
44284
|
+
if (!args.includes(flag)) {
|
|
44285
|
+
return undefined;
|
|
44286
|
+
}
|
|
44287
|
+
const index = args.indexOf(flag);
|
|
44288
|
+
const valueParts = [];
|
|
44289
|
+
for (let i = index + 1; i < args.length; i++) {
|
|
44290
|
+
const valuePart = args[i];
|
|
44291
|
+
if (valuePart === undefined) {
|
|
44292
|
+
continue;
|
|
44293
|
+
}
|
|
44294
|
+
if (KNOWN_OPTION_FLAGS.has(valuePart)) {
|
|
44295
|
+
break;
|
|
44296
|
+
}
|
|
44297
|
+
valueParts.push(valuePart);
|
|
44298
|
+
}
|
|
44299
|
+
const normalizedValue = valueParts.join(' ').trim();
|
|
44300
|
+
return normalizedValue === '' ? undefined : normalizedValue;
|
|
44301
|
+
}
|
|
44160
44302
|
/**
|
|
44161
44303
|
* Parses and validates the minimum prompt priority.
|
|
44162
44304
|
*/
|
|
@@ -44182,6 +44324,21 @@ function exitWithUsageError(message) {
|
|
|
44182
44324
|
process.exit(1);
|
|
44183
44325
|
}
|
|
44184
44326
|
|
|
44327
|
+
/**
|
|
44328
|
+
* Appends optional coding context to a runner prompt.
|
|
44329
|
+
*/
|
|
44330
|
+
function appendCoderContext(prompt, context) {
|
|
44331
|
+
const normalizedContext = context === null || context === void 0 ? void 0 : context.trim();
|
|
44332
|
+
if (!normalizedContext) {
|
|
44333
|
+
return prompt;
|
|
44334
|
+
}
|
|
44335
|
+
const normalizedPrompt = prompt.trimEnd();
|
|
44336
|
+
if (normalizedPrompt === '') {
|
|
44337
|
+
return normalizedContext;
|
|
44338
|
+
}
|
|
44339
|
+
return `${normalizedPrompt}\n\n${normalizedContext}`;
|
|
44340
|
+
}
|
|
44341
|
+
|
|
44185
44342
|
/**
|
|
44186
44343
|
* Refresh interval for the progress header in milliseconds.
|
|
44187
44344
|
*/
|
|
@@ -44193,7 +44350,7 @@ const PROGRESS_HEADER_RESERVED_LINES = 1;
|
|
|
44193
44350
|
/**
|
|
44194
44351
|
* Calendar formats used when displaying the estimated completion time.
|
|
44195
44352
|
*/
|
|
44196
|
-
const ESTIMATED_DONE_CALENDAR_FORMATS = {
|
|
44353
|
+
const ESTIMATED_DONE_CALENDAR_FORMATS$1 = {
|
|
44197
44354
|
sameDay: '[Today] h:mm',
|
|
44198
44355
|
nextDay: '[Tomorrow] h:mm',
|
|
44199
44356
|
nextWeek: 'dddd h:mm',
|
|
@@ -44292,15 +44449,15 @@ function buildProgressSnapshot(stats, startTime, initialDone) {
|
|
|
44292
44449
|
const sessionTotal = sessionDone + stats.forAgent;
|
|
44293
44450
|
const percentage = totalPrompts > 0 ? Math.round((completedPrompts / totalPrompts) * 100) : 0;
|
|
44294
44451
|
const elapsedDuration = moment.duration(moment().diff(startTime));
|
|
44295
|
-
const elapsedText = formatDurationBrief(elapsedDuration);
|
|
44452
|
+
const elapsedText = formatDurationBrief$1(elapsedDuration);
|
|
44296
44453
|
let estimatedTotalText = '—';
|
|
44297
44454
|
let estimatedLabel = 'unknown';
|
|
44298
44455
|
if (totalPrompts > 0 && completedPrompts > 0) {
|
|
44299
44456
|
const estimatedTotalMs = (elapsedDuration.asMilliseconds() * totalPrompts) / completedPrompts;
|
|
44300
44457
|
const estimatedTotalDuration = moment.duration(estimatedTotalMs);
|
|
44301
44458
|
const estimatedCompletion = startTime.clone().add(estimatedTotalDuration);
|
|
44302
|
-
estimatedTotalText = formatDurationBrief(estimatedTotalDuration);
|
|
44303
|
-
estimatedLabel = estimatedCompletion.calendar(null, ESTIMATED_DONE_CALENDAR_FORMATS);
|
|
44459
|
+
estimatedTotalText = formatDurationBrief$1(estimatedTotalDuration);
|
|
44460
|
+
estimatedLabel = estimatedCompletion.calendar(null, ESTIMATED_DONE_CALENDAR_FORMATS$1);
|
|
44304
44461
|
}
|
|
44305
44462
|
return {
|
|
44306
44463
|
totalPrompts,
|
|
@@ -44316,7 +44473,7 @@ function buildProgressSnapshot(stats, startTime, initialDone) {
|
|
|
44316
44473
|
/**
|
|
44317
44474
|
* Formats a duration into a compact string such as "3h 12m" or "45s".
|
|
44318
44475
|
*/
|
|
44319
|
-
function formatDurationBrief(duration) {
|
|
44476
|
+
function formatDurationBrief$1(duration) {
|
|
44320
44477
|
const totalSeconds = Math.max(0, Math.round(duration.asSeconds()));
|
|
44321
44478
|
const hours = Math.floor(totalSeconds / 3600);
|
|
44322
44479
|
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
@@ -44337,21 +44494,6 @@ function formatDurationBrief(duration) {
|
|
|
44337
44494
|
return parts.join(' ');
|
|
44338
44495
|
}
|
|
44339
44496
|
|
|
44340
|
-
/**
|
|
44341
|
-
* Appends optional coding context to a runner prompt.
|
|
44342
|
-
*/
|
|
44343
|
-
function appendCoderContext(prompt, context) {
|
|
44344
|
-
const normalizedContext = context === null || context === void 0 ? void 0 : context.trim();
|
|
44345
|
-
if (!normalizedContext) {
|
|
44346
|
-
return prompt;
|
|
44347
|
-
}
|
|
44348
|
-
const normalizedPrompt = prompt.trimEnd();
|
|
44349
|
-
if (normalizedPrompt === '') {
|
|
44350
|
-
return normalizedContext;
|
|
44351
|
-
}
|
|
44352
|
-
return `${normalizedPrompt}\n\n${normalizedContext}`;
|
|
44353
|
-
}
|
|
44354
|
-
|
|
44355
44497
|
/**
|
|
44356
44498
|
* Git commands used to list changed and untracked files in the working tree.
|
|
44357
44499
|
*/
|
|
@@ -44621,7 +44763,7 @@ async function waitForEnter(prompt) {
|
|
|
44621
44763
|
}
|
|
44622
44764
|
|
|
44623
44765
|
/**
|
|
44624
|
-
*
|
|
44766
|
+
* Current pause state.
|
|
44625
44767
|
*/
|
|
44626
44768
|
let pauseState = 'RUNNING';
|
|
44627
44769
|
/**
|
|
@@ -44658,17 +44800,48 @@ function listenForPause() {
|
|
|
44658
44800
|
}
|
|
44659
44801
|
/**
|
|
44660
44802
|
* If the execution is paused, it will wait until it is resumed.
|
|
44803
|
+
*
|
|
44804
|
+
* @param options.silent - When `true`, suppresses console output (used when the terminal UI handles display).
|
|
44805
|
+
* @param options.onPaused - Callback invoked when entering the PAUSED state.
|
|
44806
|
+
* @param options.onResumed - Callback invoked when leaving the PAUSED state.
|
|
44661
44807
|
*/
|
|
44662
|
-
async function checkPause() {
|
|
44808
|
+
async function checkPause(options) {
|
|
44809
|
+
var _a, _b;
|
|
44663
44810
|
if (pauseState === 'PAUSING') {
|
|
44664
44811
|
pauseState = 'PAUSED';
|
|
44665
|
-
|
|
44812
|
+
if (!(options === null || options === void 0 ? void 0 : options.silent)) {
|
|
44813
|
+
console.log(colors.bgWhite.black('Paused') + colors.gray(' (Press "p" to resume)'));
|
|
44814
|
+
}
|
|
44815
|
+
(_a = options === null || options === void 0 ? void 0 : options.onPaused) === null || _a === void 0 ? void 0 : _a.call(options);
|
|
44666
44816
|
while (pauseState === 'PAUSED') {
|
|
44667
44817
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
44668
44818
|
}
|
|
44669
|
-
|
|
44819
|
+
(_b = options === null || options === void 0 ? void 0 : options.onResumed) === null || _b === void 0 ? void 0 : _b.call(options);
|
|
44820
|
+
if (!(options === null || options === void 0 ? void 0 : options.silent)) {
|
|
44821
|
+
console.log(colors.green('Resuming...'));
|
|
44822
|
+
}
|
|
44670
44823
|
}
|
|
44671
44824
|
}
|
|
44825
|
+
/**
|
|
44826
|
+
* Returns the current pause state for external consumers such as the terminal UI.
|
|
44827
|
+
*/
|
|
44828
|
+
function getPauseState() {
|
|
44829
|
+
return pauseState;
|
|
44830
|
+
}
|
|
44831
|
+
/**
|
|
44832
|
+
* Requests a pause from an external controller (e.g. the Ink UI).
|
|
44833
|
+
*/
|
|
44834
|
+
function requestPause() {
|
|
44835
|
+
if (pauseState === 'RUNNING') {
|
|
44836
|
+
pauseState = 'PAUSING';
|
|
44837
|
+
}
|
|
44838
|
+
}
|
|
44839
|
+
/**
|
|
44840
|
+
* Resumes execution from an external controller after a pause.
|
|
44841
|
+
*/
|
|
44842
|
+
function requestResume() {
|
|
44843
|
+
pauseState = 'RUNNING';
|
|
44844
|
+
}
|
|
44672
44845
|
|
|
44673
44846
|
/**
|
|
44674
44847
|
* Environment variable that configures the name used for agent commits.
|
|
@@ -45013,7 +45186,7 @@ function stringifyUnknownError$1(error) {
|
|
|
45013
45186
|
|
|
45014
45187
|
/**
|
|
45015
45188
|
* Commits staged changes with the provided message using the dedicated coding-agent identity when configured,
|
|
45016
|
-
* otherwise falls back to the default Git configuration.
|
|
45189
|
+
* otherwise falls back to the default Git configuration. Remote pushing is opt-in via `options.autoPush`.
|
|
45017
45190
|
*/
|
|
45018
45191
|
async function commitChanges(message, options) {
|
|
45019
45192
|
const projectPath = process.cwd();
|
|
@@ -45033,7 +45206,7 @@ async function commitChanges(message, options) {
|
|
|
45033
45206
|
cwd: projectPath,
|
|
45034
45207
|
env: agentEnv,
|
|
45035
45208
|
});
|
|
45036
|
-
if (
|
|
45209
|
+
if (options === null || options === void 0 ? void 0 : options.autoPush) {
|
|
45037
45210
|
await pushCommittedChanges(projectPath, agentEnv);
|
|
45038
45211
|
}
|
|
45039
45212
|
}
|
|
@@ -46626,6 +46799,19 @@ function formatUsagePrice(usage) {
|
|
|
46626
46799
|
return `${prefix}$${price.toFixed(2)}`;
|
|
46627
46800
|
}
|
|
46628
46801
|
|
|
46802
|
+
/**
|
|
46803
|
+
* Formats optional attempt metadata stored in prompt status lines.
|
|
46804
|
+
*/
|
|
46805
|
+
function formatPromptAttemptMetadata(status, attemptCount) {
|
|
46806
|
+
if (attemptCount <= 1) {
|
|
46807
|
+
return '';
|
|
46808
|
+
}
|
|
46809
|
+
if (status === 'done') {
|
|
46810
|
+
return `(${attemptCount} attempts) `;
|
|
46811
|
+
}
|
|
46812
|
+
return `(failed after ${attemptCount} attempts) `;
|
|
46813
|
+
}
|
|
46814
|
+
|
|
46629
46815
|
/**
|
|
46630
46816
|
* Formats runner details for prompt status lines.
|
|
46631
46817
|
*/
|
|
@@ -46645,7 +46831,7 @@ function formatRunnerSignature(runnerName, modelName) {
|
|
|
46645
46831
|
/**
|
|
46646
46832
|
* Marks a prompt section as done and records usage pricing and runner details.
|
|
46647
46833
|
*/
|
|
46648
|
-
function markPromptDone(file, section, usage, runnerName, modelName, promptExecutionStartedDate) {
|
|
46834
|
+
function markPromptDone(file, section, usage, runnerName, modelName, promptExecutionStartedDate, attemptCount = 1) {
|
|
46649
46835
|
if (section.statusLineIndex === undefined) {
|
|
46650
46836
|
throw new Error(`Prompt ${section.index + 1} in ${file.name} does not have a status line.`);
|
|
46651
46837
|
}
|
|
@@ -46655,16 +46841,17 @@ function markPromptDone(file, section, usage, runnerName, modelName, promptExecu
|
|
|
46655
46841
|
}
|
|
46656
46842
|
const priceString = formatUsagePrice(usage);
|
|
46657
46843
|
const runnerSignature = formatRunnerSignature(runnerName, modelName);
|
|
46844
|
+
const attemptMetadata = formatPromptAttemptMetadata('done', attemptCount);
|
|
46658
46845
|
const duration = moment().diff(promptExecutionStartedDate);
|
|
46659
46846
|
const durationString = moment.duration(duration).humanize();
|
|
46660
46847
|
// Replace "[ ]" or "[ ] !!..." with "[x] $price duration by runner"
|
|
46661
|
-
file.lines[section.statusLineIndex] = line.replace(/\[\s*\]\s*!*\s*$/, `[x] ${priceString} ${durationString} by ${runnerSignature}`);
|
|
46848
|
+
file.lines[section.statusLineIndex] = line.replace(/\[\s*\]\s*!*\s*$/, `[x] ${attemptMetadata}${priceString} ${durationString} by ${runnerSignature}`);
|
|
46662
46849
|
}
|
|
46663
46850
|
|
|
46664
46851
|
/**
|
|
46665
46852
|
* Marks a prompt section as failed and records runner details.
|
|
46666
46853
|
*/
|
|
46667
|
-
function markPromptFailed(file, section, runnerName, modelName, promptExecutionStartedDate) {
|
|
46854
|
+
function markPromptFailed(file, section, runnerName, modelName, promptExecutionStartedDate, attemptCount = 1) {
|
|
46668
46855
|
if (section.statusLineIndex === undefined) {
|
|
46669
46856
|
throw new Error(`Prompt ${section.index + 1} in ${file.name} does not have a status line.`);
|
|
46670
46857
|
}
|
|
@@ -46673,9 +46860,11 @@ function markPromptFailed(file, section, runnerName, modelName, promptExecutionS
|
|
|
46673
46860
|
throw new Error(`Prompt ${section.index + 1} in ${file.name} points to a missing status line.`);
|
|
46674
46861
|
}
|
|
46675
46862
|
const runnerSignature = formatRunnerSignature(runnerName, modelName);
|
|
46863
|
+
const attemptMetadata = formatPromptAttemptMetadata('failed', attemptCount);
|
|
46676
46864
|
const duration = moment().diff(promptExecutionStartedDate);
|
|
46677
46865
|
const durationString = moment.duration(duration).humanize();
|
|
46678
|
-
|
|
46866
|
+
const failureDetails = attemptMetadata === '' ? `failed after ${durationString} by ${runnerSignature}` : `${attemptMetadata}${durationString} by ${runnerSignature}`;
|
|
46867
|
+
file.lines[section.statusLineIndex] = line.replace(/\[\s*\]\s*!*\s*$/, `[!] ${failureDetails}`);
|
|
46679
46868
|
}
|
|
46680
46869
|
|
|
46681
46870
|
/**
|
|
@@ -46792,6 +46981,20 @@ async function waitForPromptStart(file, section, isFirstPrompt) {
|
|
|
46792
46981
|
await waitForEnter(colors.bgWhite(`Press Enter to start the ${label}...`));
|
|
46793
46982
|
}
|
|
46794
46983
|
|
|
46984
|
+
/**
|
|
46985
|
+
* Formats one unknown error-like value into readable text for logs and feedback.
|
|
46986
|
+
*/
|
|
46987
|
+
function formatUnknownErrorDetails(error) {
|
|
46988
|
+
if (error instanceof Error) {
|
|
46989
|
+
return error.stack || error.message;
|
|
46990
|
+
}
|
|
46991
|
+
if (typeof error === 'string') {
|
|
46992
|
+
return error;
|
|
46993
|
+
}
|
|
46994
|
+
const serializedError = JSON.stringify(error, null, 2);
|
|
46995
|
+
return serializedError !== null && serializedError !== void 0 ? serializedError : String(error);
|
|
46996
|
+
}
|
|
46997
|
+
|
|
46795
46998
|
/**
|
|
46796
46999
|
* Writes the failure details for a single prompt run next to the prompt markdown file.
|
|
46797
47000
|
*/
|
|
@@ -46799,7 +47002,7 @@ async function writePromptErrorLog(options) {
|
|
|
46799
47002
|
const logPath = buildPromptErrorLogPath(options.file.path);
|
|
46800
47003
|
const label = buildPromptLabelForDisplay(options.file, options.section);
|
|
46801
47004
|
const summary = buildPromptSummary(options.file, options.section);
|
|
46802
|
-
const details =
|
|
47005
|
+
const details = formatUnknownErrorDetails(options.error);
|
|
46803
47006
|
const modelSuffix = options.modelName ? ` (${options.modelName})` : '';
|
|
46804
47007
|
const runnerLabel = `${options.runnerName || 'unknown'}${modelSuffix}`;
|
|
46805
47008
|
const log = [
|
|
@@ -46826,18 +47029,6 @@ function buildPromptErrorLogPath(promptPath) {
|
|
|
46826
47029
|
}
|
|
46827
47030
|
return `${promptPath}.error.log`;
|
|
46828
47031
|
}
|
|
46829
|
-
/**
|
|
46830
|
-
* Formats unknown error values into a readable log payload.
|
|
46831
|
-
*/
|
|
46832
|
-
function buildErrorDetails(error) {
|
|
46833
|
-
if (error instanceof Error) {
|
|
46834
|
-
return error.stack || error.message;
|
|
46835
|
-
}
|
|
46836
|
-
if (typeof error === 'string') {
|
|
46837
|
-
return error;
|
|
46838
|
-
}
|
|
46839
|
-
return JSON.stringify(error, null, 2);
|
|
46840
|
-
}
|
|
46841
47032
|
|
|
46842
47033
|
/**
|
|
46843
47034
|
* Writes updated prompt file content to disk.
|
|
@@ -47896,6 +48087,647 @@ class OpencodeRunner {
|
|
|
47896
48087
|
}
|
|
47897
48088
|
}
|
|
47898
48089
|
|
|
48090
|
+
/**
|
|
48091
|
+
* Runs the configured verification command inside the project root and returns its output.
|
|
48092
|
+
*/
|
|
48093
|
+
async function runPromptTestCommand(options) {
|
|
48094
|
+
const projectPath = toPosixPath(options.projectPath);
|
|
48095
|
+
return await $runGoScriptWithOutput({
|
|
48096
|
+
scriptPath: options.scriptPath,
|
|
48097
|
+
scriptContent: spaceTrim(`
|
|
48098
|
+
cd "${projectPath}"
|
|
48099
|
+
${options.command}
|
|
48100
|
+
`),
|
|
48101
|
+
});
|
|
48102
|
+
}
|
|
48103
|
+
|
|
48104
|
+
/**
|
|
48105
|
+
* Maximum number of coding attempts allowed for the same prompt when verification keeps failing.
|
|
48106
|
+
*/
|
|
48107
|
+
const MAX_PROMPT_TEST_ATTEMPTS = 3;
|
|
48108
|
+
/**
|
|
48109
|
+
* Maximum amount of verification output sent back to the coding agent as retry feedback.
|
|
48110
|
+
*/
|
|
48111
|
+
const MAX_TEST_FEEDBACK_OUTPUT_CHARS = 12000;
|
|
48112
|
+
/**
|
|
48113
|
+
* Runs one coding prompt and, when configured, verifies it with a shell command that can feed failures back.
|
|
48114
|
+
*/
|
|
48115
|
+
async function runPromptWithTestFeedback(options) {
|
|
48116
|
+
var _a, _b, _c, _d;
|
|
48117
|
+
const normalizedTestCommand = (_a = options.testCommand) === null || _a === void 0 ? void 0 : _a.trim();
|
|
48118
|
+
if (!normalizedTestCommand) {
|
|
48119
|
+
(_b = options.onAttemptStarted) === null || _b === void 0 ? void 0 : _b.call(options, 1);
|
|
48120
|
+
const result = await options.runner.runPrompt({
|
|
48121
|
+
prompt: options.prompt,
|
|
48122
|
+
scriptPath: options.scriptPath,
|
|
48123
|
+
projectPath: options.projectPath,
|
|
48124
|
+
});
|
|
48125
|
+
return { ...result, attemptCount: 1 };
|
|
48126
|
+
}
|
|
48127
|
+
const runPromptTestCommandExecutor = (_c = options.runPromptTestCommandExecutor) !== null && _c !== void 0 ? _c : runPromptTestCommand;
|
|
48128
|
+
let promptForCurrentAttempt = options.prompt;
|
|
48129
|
+
for (let attemptCount = 1; attemptCount <= MAX_PROMPT_TEST_ATTEMPTS; attemptCount++) {
|
|
48130
|
+
(_d = options.onAttemptStarted) === null || _d === void 0 ? void 0 : _d.call(options, attemptCount);
|
|
48131
|
+
const result = await options.runner.runPrompt({
|
|
48132
|
+
prompt: promptForCurrentAttempt,
|
|
48133
|
+
scriptPath: options.scriptPath,
|
|
48134
|
+
projectPath: options.projectPath,
|
|
48135
|
+
});
|
|
48136
|
+
console.info(colors.gray(`Running verification command after attempt #${attemptCount}: ${normalizedTestCommand}`));
|
|
48137
|
+
try {
|
|
48138
|
+
await runPromptTestCommandExecutor({
|
|
48139
|
+
command: normalizedTestCommand,
|
|
48140
|
+
projectPath: options.projectPath,
|
|
48141
|
+
scriptPath: buildPromptTestScriptPath(options.scriptPath),
|
|
48142
|
+
});
|
|
48143
|
+
return { ...result, attemptCount };
|
|
48144
|
+
}
|
|
48145
|
+
catch (error) {
|
|
48146
|
+
const fullVerificationOutput = formatUnknownErrorDetails(error);
|
|
48147
|
+
const feedbackVerificationOutput = limitVerificationOutputForFeedback(fullVerificationOutput);
|
|
48148
|
+
if (attemptCount >= MAX_PROMPT_TEST_ATTEMPTS) {
|
|
48149
|
+
console.error(colors.red(`Verification failed for ${options.promptLabel} after ${attemptCount} attempts.`));
|
|
48150
|
+
throw new Error(buildFinalVerificationFailureMessage({
|
|
48151
|
+
promptLabel: options.promptLabel,
|
|
48152
|
+
testCommand: normalizedTestCommand,
|
|
48153
|
+
attemptCount,
|
|
48154
|
+
verificationOutput: fullVerificationOutput,
|
|
48155
|
+
}));
|
|
48156
|
+
}
|
|
48157
|
+
console.warn(colors.yellow(`Verification failed for ${options.promptLabel} on attempt #${attemptCount}. Sending feedback to ${options.runner.name} and retrying...`));
|
|
48158
|
+
promptForCurrentAttempt = appendCoderContext(options.prompt, buildVerificationFeedback({
|
|
48159
|
+
testCommand: normalizedTestCommand,
|
|
48160
|
+
failedAttemptCount: attemptCount,
|
|
48161
|
+
verificationOutput: feedbackVerificationOutput,
|
|
48162
|
+
}));
|
|
48163
|
+
}
|
|
48164
|
+
}
|
|
48165
|
+
throw new Error('Unexpected prompt verification state.');
|
|
48166
|
+
}
|
|
48167
|
+
/**
|
|
48168
|
+
* Builds one feedback block appended to the next coding attempt after tests fail.
|
|
48169
|
+
*/
|
|
48170
|
+
function buildVerificationFeedback({ testCommand, failedAttemptCount, verificationOutput, }) {
|
|
48171
|
+
const nextAttemptCount = failedAttemptCount + 1;
|
|
48172
|
+
return spaceTrim((block) => `
|
|
48173
|
+
The previous implementation did not pass the required verification command.
|
|
48174
|
+
|
|
48175
|
+
## Automated verification feedback
|
|
48176
|
+
- Retry attempt: ${nextAttemptCount} of ${MAX_PROMPT_TEST_ATTEMPTS}
|
|
48177
|
+
- Verification command: \`${testCommand}\`
|
|
48178
|
+
- Update the current implementation so the verification command passes without breaking the original task requirements.
|
|
48179
|
+
|
|
48180
|
+
### Verification output
|
|
48181
|
+
\`\`\`
|
|
48182
|
+
${block(verificationOutput)}
|
|
48183
|
+
\`\`\`
|
|
48184
|
+
`);
|
|
48185
|
+
}
|
|
48186
|
+
/**
|
|
48187
|
+
* Builds the final error message written when verification still fails after all retries.
|
|
48188
|
+
*/
|
|
48189
|
+
function buildFinalVerificationFailureMessage({ promptLabel, testCommand, attemptCount, verificationOutput, }) {
|
|
48190
|
+
return spaceTrim((block) => `
|
|
48191
|
+
Verification command \`${testCommand}\` failed for \`${promptLabel}\` after ${attemptCount} attempts.
|
|
48192
|
+
|
|
48193
|
+
### Verification output
|
|
48194
|
+
\`\`\`
|
|
48195
|
+
${block(verificationOutput)}
|
|
48196
|
+
\`\`\`
|
|
48197
|
+
`);
|
|
48198
|
+
}
|
|
48199
|
+
/**
|
|
48200
|
+
* Limits verification output before it is embedded back into the next coding prompt.
|
|
48201
|
+
*/
|
|
48202
|
+
function limitVerificationOutputForFeedback(verificationOutput) {
|
|
48203
|
+
const normalizedVerificationOutput = verificationOutput.trim();
|
|
48204
|
+
if (normalizedVerificationOutput.length <= MAX_TEST_FEEDBACK_OUTPUT_CHARS) {
|
|
48205
|
+
return normalizedVerificationOutput;
|
|
48206
|
+
}
|
|
48207
|
+
return spaceTrim(`
|
|
48208
|
+
[...verification output truncated to the last ${MAX_TEST_FEEDBACK_OUTPUT_CHARS} characters...]
|
|
48209
|
+
${normalizedVerificationOutput.slice(-MAX_TEST_FEEDBACK_OUTPUT_CHARS)}
|
|
48210
|
+
`);
|
|
48211
|
+
}
|
|
48212
|
+
/**
|
|
48213
|
+
* Derives a dedicated temp-script path for verification commands.
|
|
48214
|
+
*/
|
|
48215
|
+
function buildPromptTestScriptPath(scriptPath) {
|
|
48216
|
+
if (scriptPath.toLowerCase().endsWith('.sh')) {
|
|
48217
|
+
return `${scriptPath.slice(0, -3)}.test.sh`;
|
|
48218
|
+
}
|
|
48219
|
+
return `${scriptPath}.test.sh`;
|
|
48220
|
+
}
|
|
48221
|
+
|
|
48222
|
+
/**
|
|
48223
|
+
* Maximum number of agent output lines kept in the scrolling output area.
|
|
48224
|
+
*
|
|
48225
|
+
* @private internal constant of coder run UI
|
|
48226
|
+
*/
|
|
48227
|
+
const MAX_AGENT_OUTPUT_LINES = 12;
|
|
48228
|
+
/**
|
|
48229
|
+
* Calendar formats used when displaying the estimated completion time.
|
|
48230
|
+
*
|
|
48231
|
+
* @private internal constant of coder run UI
|
|
48232
|
+
*/
|
|
48233
|
+
const ESTIMATED_DONE_CALENDAR_FORMATS = {
|
|
48234
|
+
sameDay: '[Today] h:mm',
|
|
48235
|
+
nextDay: '[Tomorrow] h:mm',
|
|
48236
|
+
nextWeek: 'dddd h:mm',
|
|
48237
|
+
lastDay: '[Yesterday] h:mm',
|
|
48238
|
+
lastWeek: 'dddd h:mm',
|
|
48239
|
+
sameElse: 'MMM D h:mm',
|
|
48240
|
+
};
|
|
48241
|
+
/**
|
|
48242
|
+
* Reactive state manager for the coder run terminal UI.
|
|
48243
|
+
*
|
|
48244
|
+
* Holds all data the Ink components need and emits `'change'` events
|
|
48245
|
+
* whenever any property is updated so the UI can re-render.
|
|
48246
|
+
*
|
|
48247
|
+
* @private internal utility of coder run UI
|
|
48248
|
+
*/
|
|
48249
|
+
class CoderRunUiState extends EventEmitter {
|
|
48250
|
+
constructor(startTime) {
|
|
48251
|
+
super();
|
|
48252
|
+
this.config = { agentName: '', priority: 0 };
|
|
48253
|
+
this.currentPromptLabel = '';
|
|
48254
|
+
this.currentAttempt = 1;
|
|
48255
|
+
this.maxAttempts = 3;
|
|
48256
|
+
this.agentOutputLines = [];
|
|
48257
|
+
this.phase = 'initializing';
|
|
48258
|
+
this.statusMessage = 'Initializing...';
|
|
48259
|
+
this.errors = [];
|
|
48260
|
+
this.stats = { done: 0, forAgent: 0, belowMinimumPriority: 0, toBeWritten: 0 };
|
|
48261
|
+
/**
|
|
48262
|
+
* Total milliseconds the timer was paused/waiting (excluded from elapsed display).
|
|
48263
|
+
*/
|
|
48264
|
+
this.pausedMs = 0;
|
|
48265
|
+
this.startTime = startTime;
|
|
48266
|
+
// Timer starts paused — callers call `resumeTimer()` when actual work begins.
|
|
48267
|
+
this.pausedSince = startTime.clone();
|
|
48268
|
+
}
|
|
48269
|
+
/**
|
|
48270
|
+
* Pauses the elapsed timer (e.g. while waiting for user input or paused state).
|
|
48271
|
+
*/
|
|
48272
|
+
pauseTimer() {
|
|
48273
|
+
if (this.pausedSince === undefined) {
|
|
48274
|
+
this.pausedSince = moment();
|
|
48275
|
+
}
|
|
48276
|
+
}
|
|
48277
|
+
/**
|
|
48278
|
+
* Resumes the elapsed timer after a pause.
|
|
48279
|
+
*/
|
|
48280
|
+
resumeTimer() {
|
|
48281
|
+
if (this.pausedSince !== undefined) {
|
|
48282
|
+
this.pausedMs += moment().diff(this.pausedSince);
|
|
48283
|
+
this.pausedSince = undefined;
|
|
48284
|
+
}
|
|
48285
|
+
}
|
|
48286
|
+
/**
|
|
48287
|
+
* Replaces the configuration shown in the UI header.
|
|
48288
|
+
*/
|
|
48289
|
+
setConfig(config) {
|
|
48290
|
+
this.config = config;
|
|
48291
|
+
this.emitChange();
|
|
48292
|
+
}
|
|
48293
|
+
/**
|
|
48294
|
+
* Feeds new prompt statistics from the main loop so the progress bar updates.
|
|
48295
|
+
*/
|
|
48296
|
+
updateProgress(stats) {
|
|
48297
|
+
if (this.initialDone === undefined && (stats.done > 0 || stats.forAgent > 0 || stats.toBeWritten > 0)) {
|
|
48298
|
+
this.initialDone = stats.done;
|
|
48299
|
+
}
|
|
48300
|
+
this.stats = stats;
|
|
48301
|
+
this.emitChange();
|
|
48302
|
+
}
|
|
48303
|
+
/**
|
|
48304
|
+
* Computes a progress snapshot on demand so elapsed time ticks with periodic re-renders.
|
|
48305
|
+
*/
|
|
48306
|
+
getProgress() {
|
|
48307
|
+
var _a;
|
|
48308
|
+
const stats = this.stats;
|
|
48309
|
+
const totalPrompts = stats.done + stats.forAgent + stats.toBeWritten;
|
|
48310
|
+
const sessionDone = Math.max(0, stats.done - ((_a = this.initialDone) !== null && _a !== void 0 ? _a : stats.done));
|
|
48311
|
+
const sessionTotal = sessionDone + stats.forAgent;
|
|
48312
|
+
const percentage = totalPrompts > 0 ? Math.round((stats.done / totalPrompts) * 100) : 0;
|
|
48313
|
+
const wallMs = moment().diff(this.startTime);
|
|
48314
|
+
const currentPauseMs = this.pausedSince !== undefined ? moment().diff(this.pausedSince) : 0;
|
|
48315
|
+
const activeMs = Math.max(0, wallMs - this.pausedMs - currentPauseMs);
|
|
48316
|
+
const elapsedDuration = moment.duration(activeMs);
|
|
48317
|
+
const elapsedText = formatDurationBrief(elapsedDuration);
|
|
48318
|
+
let estimatedTotalText = '\u2014';
|
|
48319
|
+
let estimatedLabel = 'unknown';
|
|
48320
|
+
if (totalPrompts > 0 && stats.done > 0) {
|
|
48321
|
+
const estimatedTotalMs = (elapsedDuration.asMilliseconds() * totalPrompts) / stats.done;
|
|
48322
|
+
const estimatedRemainingMs = estimatedTotalMs - elapsedDuration.asMilliseconds();
|
|
48323
|
+
const estimatedTotalDuration = moment.duration(estimatedTotalMs);
|
|
48324
|
+
const estimatedCompletion = moment().add(estimatedRemainingMs, 'milliseconds');
|
|
48325
|
+
estimatedTotalText = formatDurationBrief(estimatedTotalDuration);
|
|
48326
|
+
estimatedLabel = estimatedCompletion.calendar(null, ESTIMATED_DONE_CALENDAR_FORMATS);
|
|
48327
|
+
}
|
|
48328
|
+
return {
|
|
48329
|
+
totalPrompts,
|
|
48330
|
+
sessionDone,
|
|
48331
|
+
sessionTotal,
|
|
48332
|
+
percentage,
|
|
48333
|
+
elapsedText,
|
|
48334
|
+
estimatedTotalText,
|
|
48335
|
+
estimatedLabel,
|
|
48336
|
+
};
|
|
48337
|
+
}
|
|
48338
|
+
/**
|
|
48339
|
+
* Sets the label of the prompt currently being processed and resets per-prompt state.
|
|
48340
|
+
*/
|
|
48341
|
+
setCurrentPrompt(label) {
|
|
48342
|
+
this.currentPromptLabel = label;
|
|
48343
|
+
this.agentOutputLines = [];
|
|
48344
|
+
this.currentAttempt = 1;
|
|
48345
|
+
this.emitChange();
|
|
48346
|
+
}
|
|
48347
|
+
/**
|
|
48348
|
+
* Updates the current retry attempt number.
|
|
48349
|
+
*/
|
|
48350
|
+
setAttempt(attempt) {
|
|
48351
|
+
this.currentAttempt = attempt;
|
|
48352
|
+
this.emitChange();
|
|
48353
|
+
}
|
|
48354
|
+
/**
|
|
48355
|
+
* Appends raw agent output text, keeping only the last `MAX_AGENT_OUTPUT_LINES`.
|
|
48356
|
+
*/
|
|
48357
|
+
addAgentOutput(text) {
|
|
48358
|
+
const lines = text.split(/\r?\n/).filter((line) => line.trim() !== '');
|
|
48359
|
+
if (lines.length === 0) {
|
|
48360
|
+
return;
|
|
48361
|
+
}
|
|
48362
|
+
this.agentOutputLines.push(...lines);
|
|
48363
|
+
if (this.agentOutputLines.length > MAX_AGENT_OUTPUT_LINES) {
|
|
48364
|
+
this.agentOutputLines = this.agentOutputLines.slice(-MAX_AGENT_OUTPUT_LINES);
|
|
48365
|
+
}
|
|
48366
|
+
this.emitChange();
|
|
48367
|
+
}
|
|
48368
|
+
/**
|
|
48369
|
+
* Transitions the execution phase shown in the UI.
|
|
48370
|
+
*/
|
|
48371
|
+
setPhase(phase) {
|
|
48372
|
+
this.phase = phase;
|
|
48373
|
+
this.emitChange();
|
|
48374
|
+
}
|
|
48375
|
+
/**
|
|
48376
|
+
* Updates the status message line beneath the current prompt label.
|
|
48377
|
+
*/
|
|
48378
|
+
setStatusMessage(message) {
|
|
48379
|
+
this.statusMessage = message;
|
|
48380
|
+
this.emitChange();
|
|
48381
|
+
}
|
|
48382
|
+
/**
|
|
48383
|
+
* Appends an error message to the error list shown in the UI.
|
|
48384
|
+
*/
|
|
48385
|
+
addError(errorMessage) {
|
|
48386
|
+
this.errors.push(errorMessage);
|
|
48387
|
+
this.emitChange();
|
|
48388
|
+
}
|
|
48389
|
+
emitChange() {
|
|
48390
|
+
this.emit('change');
|
|
48391
|
+
}
|
|
48392
|
+
}
|
|
48393
|
+
/**
|
|
48394
|
+
* Formats a duration into a compact string such as "3h 12m" or "45s".
|
|
48395
|
+
*
|
|
48396
|
+
* @private internal utility of coder run UI
|
|
48397
|
+
*/
|
|
48398
|
+
function formatDurationBrief(duration) {
|
|
48399
|
+
const totalSeconds = Math.max(0, Math.round(duration.asSeconds()));
|
|
48400
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
48401
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
48402
|
+
const seconds = totalSeconds % 60;
|
|
48403
|
+
const parts = [];
|
|
48404
|
+
if (hours > 0) {
|
|
48405
|
+
parts.push(`${hours}h`);
|
|
48406
|
+
}
|
|
48407
|
+
if (minutes > 0) {
|
|
48408
|
+
parts.push(`${minutes}m`);
|
|
48409
|
+
}
|
|
48410
|
+
if (!parts.length && seconds > 0) {
|
|
48411
|
+
parts.push(`${seconds}s`);
|
|
48412
|
+
}
|
|
48413
|
+
if (!parts.length) {
|
|
48414
|
+
parts.push('0s');
|
|
48415
|
+
}
|
|
48416
|
+
return parts.join(' ');
|
|
48417
|
+
}
|
|
48418
|
+
|
|
48419
|
+
/**
|
|
48420
|
+
* Refresh interval for the terminal UI in milliseconds.
|
|
48421
|
+
*
|
|
48422
|
+
* @private internal constant of coder run UI
|
|
48423
|
+
*/
|
|
48424
|
+
const UI_REFRESH_INTERVAL_MS = 200;
|
|
48425
|
+
/**
|
|
48426
|
+
* Character width used for the text progress bar.
|
|
48427
|
+
*
|
|
48428
|
+
* @private internal constant of coder run UI
|
|
48429
|
+
*/
|
|
48430
|
+
const PROGRESS_BAR_WIDTH = 40;
|
|
48431
|
+
/**
|
|
48432
|
+
* Maximum number of output lines reserved for agent output in the UI.
|
|
48433
|
+
*
|
|
48434
|
+
* @private internal constant of coder run UI
|
|
48435
|
+
*/
|
|
48436
|
+
const MAX_VISIBLE_OUTPUT_LINES = 8;
|
|
48437
|
+
/**
|
|
48438
|
+
* Spinner animation frames.
|
|
48439
|
+
*
|
|
48440
|
+
* @private internal constant of coder run UI
|
|
48441
|
+
*/
|
|
48442
|
+
const SPINNER_FRAMES = [
|
|
48443
|
+
'\u280B',
|
|
48444
|
+
'\u2819',
|
|
48445
|
+
'\u2839',
|
|
48446
|
+
'\u2838',
|
|
48447
|
+
'\u283C',
|
|
48448
|
+
'\u2834',
|
|
48449
|
+
'\u2826',
|
|
48450
|
+
'\u2827',
|
|
48451
|
+
'\u2807',
|
|
48452
|
+
'\u280F',
|
|
48453
|
+
];
|
|
48454
|
+
/**
|
|
48455
|
+
* Strips ANSI escape codes from a string.
|
|
48456
|
+
*
|
|
48457
|
+
* @private internal utility of coder run UI
|
|
48458
|
+
*/
|
|
48459
|
+
function stripAnsi(text) {
|
|
48460
|
+
// eslint-disable-next-line no-control-regex
|
|
48461
|
+
return text.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, '');
|
|
48462
|
+
}
|
|
48463
|
+
/**
|
|
48464
|
+
* Returns the usable terminal width, capped at 80.
|
|
48465
|
+
*
|
|
48466
|
+
* @private internal utility of coder run UI
|
|
48467
|
+
*/
|
|
48468
|
+
function getTerminalWidth() {
|
|
48469
|
+
return Math.min(process.stdout.columns || 80, 80);
|
|
48470
|
+
}
|
|
48471
|
+
/**
|
|
48472
|
+
* Builds a text progress bar string from a percentage.
|
|
48473
|
+
*
|
|
48474
|
+
* @private internal utility of coder run UI
|
|
48475
|
+
*/
|
|
48476
|
+
function buildProgressBar(percentage) {
|
|
48477
|
+
const filled = Math.round((percentage / 100) * PROGRESS_BAR_WIDTH);
|
|
48478
|
+
const empty = PROGRESS_BAR_WIDTH - filled;
|
|
48479
|
+
return colors.green('\u2588'.repeat(filled)) + colors.gray('\u2591'.repeat(empty)) + ` ${percentage}%`;
|
|
48480
|
+
}
|
|
48481
|
+
/**
|
|
48482
|
+
* Boots the ANSI terminal UI for `ptbk coder run`.
|
|
48483
|
+
*
|
|
48484
|
+
* The UI reserves a fixed number of terminal lines and repaints them periodically.
|
|
48485
|
+
* Between repaints, any console output from runners is captured and fed into the
|
|
48486
|
+
* scrolling agent-output area.
|
|
48487
|
+
*
|
|
48488
|
+
* On non-interactive (non-TTY) terminals the UI is skipped entirely and
|
|
48489
|
+
* only the state object is provided.
|
|
48490
|
+
*
|
|
48491
|
+
* @private internal entry point of coder run UI
|
|
48492
|
+
*/
|
|
48493
|
+
function renderCoderRunUi(startTime) {
|
|
48494
|
+
const state = new CoderRunUiState(startTime);
|
|
48495
|
+
if (!process.stdout.isTTY) {
|
|
48496
|
+
return {
|
|
48497
|
+
state,
|
|
48498
|
+
startCapturingAgentOutput: () => { },
|
|
48499
|
+
stopCapturingAgentOutput: () => { },
|
|
48500
|
+
cleanup: () => { },
|
|
48501
|
+
};
|
|
48502
|
+
}
|
|
48503
|
+
// --- Console interception ---
|
|
48504
|
+
const originalConsoleInfo = console.info;
|
|
48505
|
+
const originalConsoleWarn = console.warn;
|
|
48506
|
+
const originalConsoleError = console.error;
|
|
48507
|
+
const originalConsoleLog = console.log;
|
|
48508
|
+
let isCapturing = false;
|
|
48509
|
+
console.info = (...args) => {
|
|
48510
|
+
if (isCapturing) {
|
|
48511
|
+
state.addAgentOutput(args.map(String).join(' '));
|
|
48512
|
+
}
|
|
48513
|
+
// In UI mode, non-captured output is intentionally suppressed
|
|
48514
|
+
// so it does not interfere with the repainted frame.
|
|
48515
|
+
};
|
|
48516
|
+
console.warn = (...args) => {
|
|
48517
|
+
if (isCapturing) {
|
|
48518
|
+
state.addAgentOutput(args.map(String).join(' '));
|
|
48519
|
+
}
|
|
48520
|
+
};
|
|
48521
|
+
console.error = (...args) => {
|
|
48522
|
+
if (isCapturing) {
|
|
48523
|
+
state.addError(args.map(String).join(' '));
|
|
48524
|
+
}
|
|
48525
|
+
};
|
|
48526
|
+
console.log = (...args) => {
|
|
48527
|
+
if (isCapturing) {
|
|
48528
|
+
state.addAgentOutput(args.map(String).join(' '));
|
|
48529
|
+
}
|
|
48530
|
+
};
|
|
48531
|
+
// --- Keyboard input (pause) ---
|
|
48532
|
+
const readline = require('readline');
|
|
48533
|
+
readline.emitKeypressEvents(process.stdin);
|
|
48534
|
+
if (process.stdin.isTTY) {
|
|
48535
|
+
process.stdin.setRawMode(true);
|
|
48536
|
+
}
|
|
48537
|
+
const keypressHandler = (_str, key) => {
|
|
48538
|
+
if (key.ctrl && key.name === 'c') {
|
|
48539
|
+
cleanup();
|
|
48540
|
+
process.exit(0);
|
|
48541
|
+
}
|
|
48542
|
+
if (key.name === 'p') {
|
|
48543
|
+
const current = getPauseState();
|
|
48544
|
+
if (current === 'RUNNING') {
|
|
48545
|
+
requestPause();
|
|
48546
|
+
}
|
|
48547
|
+
else {
|
|
48548
|
+
requestResume();
|
|
48549
|
+
}
|
|
48550
|
+
}
|
|
48551
|
+
};
|
|
48552
|
+
process.stdin.on('keypress', keypressHandler);
|
|
48553
|
+
// --- Rendering ---
|
|
48554
|
+
let spinnerFrame = 0;
|
|
48555
|
+
let previousFrameLineCount = 0;
|
|
48556
|
+
let isRendering = false;
|
|
48557
|
+
let renderScheduled = false;
|
|
48558
|
+
/**
|
|
48559
|
+
* Schedules a render on the next tick if one isn't already pending.
|
|
48560
|
+
* Prevents overlapping renders that cause cursor desync.
|
|
48561
|
+
*/
|
|
48562
|
+
function scheduleRender() {
|
|
48563
|
+
if (renderScheduled) {
|
|
48564
|
+
return;
|
|
48565
|
+
}
|
|
48566
|
+
renderScheduled = true;
|
|
48567
|
+
setImmediate(() => {
|
|
48568
|
+
renderScheduled = false;
|
|
48569
|
+
render();
|
|
48570
|
+
});
|
|
48571
|
+
}
|
|
48572
|
+
/**
|
|
48573
|
+
* Clears previously rendered lines and writes a new frame.
|
|
48574
|
+
*/
|
|
48575
|
+
function render() {
|
|
48576
|
+
if (isRendering) {
|
|
48577
|
+
return;
|
|
48578
|
+
}
|
|
48579
|
+
isRendering = true;
|
|
48580
|
+
try {
|
|
48581
|
+
const lines = buildFrame();
|
|
48582
|
+
// Move cursor up to clear the previous frame.
|
|
48583
|
+
if (previousFrameLineCount > 0) {
|
|
48584
|
+
process.stdout.write(`\x1b[${previousFrameLineCount}A`);
|
|
48585
|
+
}
|
|
48586
|
+
for (let i = 0; i < lines.length; i++) {
|
|
48587
|
+
clearLine(process.stdout, 0);
|
|
48588
|
+
cursorTo(process.stdout, 0);
|
|
48589
|
+
process.stdout.write(lines[i]);
|
|
48590
|
+
if (i < lines.length - 1) {
|
|
48591
|
+
process.stdout.write('\n');
|
|
48592
|
+
}
|
|
48593
|
+
}
|
|
48594
|
+
// Clear any leftover lines from a previous longer frame.
|
|
48595
|
+
if (lines.length < previousFrameLineCount) {
|
|
48596
|
+
for (let i = lines.length; i < previousFrameLineCount; i++) {
|
|
48597
|
+
process.stdout.write('\n');
|
|
48598
|
+
clearLine(process.stdout, 0);
|
|
48599
|
+
cursorTo(process.stdout, 0);
|
|
48600
|
+
}
|
|
48601
|
+
// Move back up to the end of the current frame.
|
|
48602
|
+
const overshoot = previousFrameLineCount - lines.length;
|
|
48603
|
+
if (overshoot > 0) {
|
|
48604
|
+
process.stdout.write(`\x1b[${overshoot}A`);
|
|
48605
|
+
}
|
|
48606
|
+
}
|
|
48607
|
+
previousFrameLineCount = lines.length;
|
|
48608
|
+
spinnerFrame = (spinnerFrame + 1) % SPINNER_FRAMES.length;
|
|
48609
|
+
}
|
|
48610
|
+
finally {
|
|
48611
|
+
isRendering = false;
|
|
48612
|
+
}
|
|
48613
|
+
}
|
|
48614
|
+
/**
|
|
48615
|
+
* Builds the complete frame as an array of terminal lines.
|
|
48616
|
+
*/
|
|
48617
|
+
function buildFrame() {
|
|
48618
|
+
const w = getTerminalWidth();
|
|
48619
|
+
const sep = colors.gray('\u2500'.repeat(w - 2));
|
|
48620
|
+
const spinner = SPINNER_FRAMES[spinnerFrame];
|
|
48621
|
+
const { config, phase, currentPromptLabel, currentAttempt, maxAttempts, statusMessage, agentOutputLines, errors, } = state;
|
|
48622
|
+
const progress = state.getProgress();
|
|
48623
|
+
const isPaused = getPauseState() !== 'RUNNING';
|
|
48624
|
+
const isActive = phase === 'running' || phase === 'verifying' || phase === 'loading';
|
|
48625
|
+
const lines = [];
|
|
48626
|
+
// --- Branding ---
|
|
48627
|
+
lines.push(colors.bold.cyan('\u2728 Promptbook Coder'));
|
|
48628
|
+
// --- Config ---
|
|
48629
|
+
let configLine1 = `Agent: ${colors.bold.green(config.agentName)}`;
|
|
48630
|
+
if (config.modelName) {
|
|
48631
|
+
configLine1 += ` \u2502 Model: ${colors.bold(config.modelName)}`;
|
|
48632
|
+
}
|
|
48633
|
+
if (config.thinkingLevel) {
|
|
48634
|
+
configLine1 += ` \u2502 Thinking: ${colors.bold(config.thinkingLevel)}`;
|
|
48635
|
+
}
|
|
48636
|
+
lines.push(configLine1);
|
|
48637
|
+
let configLine2 = '';
|
|
48638
|
+
if (config.context) {
|
|
48639
|
+
configLine2 += `Context: ${colors.yellow(config.context)} \u2502 `;
|
|
48640
|
+
}
|
|
48641
|
+
configLine2 += `Priority: \u2265${config.priority}`;
|
|
48642
|
+
if (config.testCommand) {
|
|
48643
|
+
configLine2 += ` \u2502 Test: ${colors.gray(config.testCommand)}`;
|
|
48644
|
+
}
|
|
48645
|
+
lines.push(configLine2);
|
|
48646
|
+
// --- Separator ---
|
|
48647
|
+
lines.push(sep);
|
|
48648
|
+
// --- Progress ---
|
|
48649
|
+
const progressSummary = [
|
|
48650
|
+
`${progress.sessionDone}/${progress.sessionTotal} Prompts (${progress.totalPrompts} total)`,
|
|
48651
|
+
`${progress.elapsedText}/${progress.estimatedTotalText}`,
|
|
48652
|
+
`Est. done ${progress.estimatedLabel}`,
|
|
48653
|
+
].join(' \u2502 ');
|
|
48654
|
+
lines.push(progressSummary);
|
|
48655
|
+
lines.push(buildProgressBar(progress.percentage));
|
|
48656
|
+
// --- Separator ---
|
|
48657
|
+
lines.push(sep);
|
|
48658
|
+
// --- Current prompt ---
|
|
48659
|
+
if (currentPromptLabel) {
|
|
48660
|
+
const spinnerPrefix = isActive ? colors.yellow(`${spinner} `) : ' ';
|
|
48661
|
+
lines.push(spinnerPrefix + colors.bold(currentPromptLabel));
|
|
48662
|
+
lines.push(colors.gray(`Attempt ${currentAttempt}/${maxAttempts} \u2502 ${statusMessage}`));
|
|
48663
|
+
}
|
|
48664
|
+
else {
|
|
48665
|
+
lines.push(colors.gray(statusMessage));
|
|
48666
|
+
}
|
|
48667
|
+
// --- Agent output ---
|
|
48668
|
+
if (agentOutputLines.length > 0) {
|
|
48669
|
+
lines.push('');
|
|
48670
|
+
lines.push(colors.gray.bold('Agent output:'));
|
|
48671
|
+
const visibleLines = agentOutputLines.slice(-MAX_VISIBLE_OUTPUT_LINES);
|
|
48672
|
+
for (const line of visibleLines) {
|
|
48673
|
+
const cleanLine = stripAnsi(line);
|
|
48674
|
+
// Truncate to terminal width.
|
|
48675
|
+
const truncated = cleanLine.length > w - 2 ? cleanLine.slice(0, w - 5) + '...' : cleanLine;
|
|
48676
|
+
lines.push(colors.gray(truncated));
|
|
48677
|
+
}
|
|
48678
|
+
}
|
|
48679
|
+
// --- Errors ---
|
|
48680
|
+
if (errors.length > 0) {
|
|
48681
|
+
lines.push('');
|
|
48682
|
+
for (const err of errors) {
|
|
48683
|
+
lines.push(colors.red(`\u2717 ${err}`));
|
|
48684
|
+
}
|
|
48685
|
+
}
|
|
48686
|
+
// --- Separator ---
|
|
48687
|
+
lines.push(sep);
|
|
48688
|
+
// --- Controls ---
|
|
48689
|
+
const pauseLabel = isPaused
|
|
48690
|
+
? colors.bgYellow.black(' PAUSED ') + colors.gray(' [P] Resume \u2502 Ctrl+C Exit')
|
|
48691
|
+
: colors.gray('[P] Pause \u2502 Ctrl+C Exit');
|
|
48692
|
+
lines.push(pauseLabel);
|
|
48693
|
+
return lines;
|
|
48694
|
+
}
|
|
48695
|
+
// Initial render.
|
|
48696
|
+
process.stdout.write('\n');
|
|
48697
|
+
render();
|
|
48698
|
+
const interval = setInterval(scheduleRender, UI_REFRESH_INTERVAL_MS);
|
|
48699
|
+
// Listen for state changes and schedule a re-render (debounced).
|
|
48700
|
+
state.on('change', scheduleRender);
|
|
48701
|
+
// --- Cleanup ---
|
|
48702
|
+
function cleanup() {
|
|
48703
|
+
clearInterval(interval);
|
|
48704
|
+
state.off('change', scheduleRender);
|
|
48705
|
+
process.stdin.off('keypress', keypressHandler);
|
|
48706
|
+
if (process.stdin.isTTY) {
|
|
48707
|
+
process.stdin.setRawMode(false);
|
|
48708
|
+
}
|
|
48709
|
+
isCapturing = false;
|
|
48710
|
+
console.info = originalConsoleInfo;
|
|
48711
|
+
console.warn = originalConsoleWarn;
|
|
48712
|
+
console.error = originalConsoleError;
|
|
48713
|
+
console.log = originalConsoleLog;
|
|
48714
|
+
// Render one final frame so the user sees the last state.
|
|
48715
|
+
render();
|
|
48716
|
+
process.stdout.write('\n');
|
|
48717
|
+
}
|
|
48718
|
+
return {
|
|
48719
|
+
state,
|
|
48720
|
+
startCapturingAgentOutput() {
|
|
48721
|
+
isCapturing = true;
|
|
48722
|
+
},
|
|
48723
|
+
stopCapturingAgentOutput() {
|
|
48724
|
+
isCapturing = false;
|
|
48725
|
+
},
|
|
48726
|
+
cleanup,
|
|
48727
|
+
};
|
|
48728
|
+
}
|
|
48729
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
48730
|
+
|
|
47899
48731
|
/**
|
|
47900
48732
|
* Constant for prompts dir.
|
|
47901
48733
|
*/
|
|
@@ -47958,8 +48790,13 @@ async function runCodexPrompts(providedOptions) {
|
|
|
47958
48790
|
`));
|
|
47959
48791
|
}
|
|
47960
48792
|
const runStartDate = moment();
|
|
47961
|
-
const
|
|
47962
|
-
|
|
48793
|
+
const isUiMode = !options.dryRun && Boolean(process.stdout.isTTY);
|
|
48794
|
+
const progressDisplay = options.dryRun || isUiMode ? undefined : new CliProgressDisplay(runStartDate);
|
|
48795
|
+
const uiHandle = isUiMode ? renderCoderRunUi(runStartDate) : undefined;
|
|
48796
|
+
// When the Ink UI is active it handles keyboard input itself, so skip the raw stdin listener.
|
|
48797
|
+
if (!isUiMode) {
|
|
48798
|
+
listenForPause();
|
|
48799
|
+
}
|
|
47963
48800
|
try {
|
|
47964
48801
|
const resolvedCoderContext = await resolveCoderContext(options.context, process.cwd());
|
|
47965
48802
|
if (options.dryRun) {
|
|
@@ -48058,35 +48895,78 @@ async function runCodexPrompts(providedOptions) {
|
|
|
48058
48895
|
}
|
|
48059
48896
|
console.info(colors.green(`Running prompts with ${runner.name}`));
|
|
48060
48897
|
const runnerMetadata = getRunnerMetadata(options, actualRunnerModel);
|
|
48898
|
+
// Feed configuration into the terminal UI
|
|
48899
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setConfig({
|
|
48900
|
+
agentName: runner.name,
|
|
48901
|
+
modelName: actualRunnerModel,
|
|
48902
|
+
thinkingLevel: options.thinkingLevel,
|
|
48903
|
+
context: options.context,
|
|
48904
|
+
priority: options.priority,
|
|
48905
|
+
testCommand: options.testCommand,
|
|
48906
|
+
});
|
|
48907
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('loading');
|
|
48908
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Running prompts with ${runner.name}`);
|
|
48061
48909
|
let hasShownUpcomingTasks = false;
|
|
48062
48910
|
let hasWaitedForStart = false;
|
|
48063
48911
|
while (just(true)) {
|
|
48064
|
-
await checkPause(
|
|
48912
|
+
await checkPause({
|
|
48913
|
+
silent: isUiMode,
|
|
48914
|
+
onPaused: () => {
|
|
48915
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
48916
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('paused');
|
|
48917
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Paused');
|
|
48918
|
+
},
|
|
48919
|
+
onResumed: () => {
|
|
48920
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
48921
|
+
},
|
|
48922
|
+
});
|
|
48923
|
+
if (isUiMode) {
|
|
48924
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('loading');
|
|
48925
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Loading prompts...');
|
|
48926
|
+
}
|
|
48065
48927
|
const promptFiles = await loadPromptFiles(PROMPTS_DIR$1);
|
|
48066
48928
|
const stats = summarizePrompts(promptFiles, options.priority);
|
|
48067
48929
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.update(stats);
|
|
48068
|
-
|
|
48930
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.updateProgress(stats);
|
|
48931
|
+
if (!isUiMode) {
|
|
48932
|
+
printStats(stats, options.priority);
|
|
48933
|
+
}
|
|
48069
48934
|
const nextPrompt = findNextTodoPrompt(promptFiles, options.priority);
|
|
48070
48935
|
if (!hasShownUpcomingTasks) {
|
|
48071
|
-
if (stats.toBeWritten > 0) {
|
|
48936
|
+
if (stats.toBeWritten > 0 && !isUiMode) {
|
|
48072
48937
|
console.info(colors.yellow('Following prompts need to be written:'));
|
|
48073
48938
|
printPromptsToBeWritten(promptFiles, options.priority);
|
|
48074
48939
|
console.info('');
|
|
48075
48940
|
}
|
|
48076
|
-
|
|
48941
|
+
if (!isUiMode) {
|
|
48942
|
+
printUpcomingTasks(listUpcomingTasks(promptFiles, options.priority));
|
|
48943
|
+
}
|
|
48077
48944
|
hasShownUpcomingTasks = true;
|
|
48078
48945
|
}
|
|
48079
48946
|
if (!nextPrompt) {
|
|
48080
48947
|
if (stats.toBeWritten > 0) {
|
|
48081
|
-
|
|
48948
|
+
const message = 'No prompts ready for agent.';
|
|
48949
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(message);
|
|
48950
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('done');
|
|
48951
|
+
if (!isUiMode) {
|
|
48952
|
+
console.info(colors.yellow(message));
|
|
48953
|
+
}
|
|
48082
48954
|
}
|
|
48083
48955
|
else {
|
|
48084
|
-
|
|
48956
|
+
const message = 'All prompts are done.';
|
|
48957
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(message);
|
|
48958
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('done');
|
|
48959
|
+
if (!isUiMode) {
|
|
48960
|
+
console.info(colors.green(message));
|
|
48961
|
+
}
|
|
48085
48962
|
}
|
|
48086
48963
|
return;
|
|
48087
48964
|
}
|
|
48088
48965
|
if (options.waitForUser) {
|
|
48966
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
48967
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(hasWaitedForStart ? 'Waiting... Press Enter to continue' : 'Waiting... Press Enter to start');
|
|
48089
48968
|
await waitForPromptStart(nextPrompt.file, nextPrompt.section, !hasWaitedForStart);
|
|
48969
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
48090
48970
|
hasWaitedForStart = true;
|
|
48091
48971
|
}
|
|
48092
48972
|
if (!options.ignoreGitChanges) {
|
|
@@ -48096,29 +48976,57 @@ async function runCodexPrompts(providedOptions) {
|
|
|
48096
48976
|
const codexPrompt = appendCoderContext(buildCodexPrompt(nextPrompt.file, nextPrompt.section), resolvedCoderContext);
|
|
48097
48977
|
const scriptPath = buildScriptPath(nextPrompt.file, nextPrompt.section);
|
|
48098
48978
|
const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section);
|
|
48099
|
-
|
|
48979
|
+
if (isUiMode) {
|
|
48980
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentPrompt(promptLabel);
|
|
48981
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('running');
|
|
48982
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Running');
|
|
48983
|
+
}
|
|
48984
|
+
else {
|
|
48985
|
+
console.info(colors.blue(`Processing ${promptLabel}`));
|
|
48986
|
+
}
|
|
48100
48987
|
const promptExecutionStartedDate = moment();
|
|
48988
|
+
let attemptCount = 1;
|
|
48101
48989
|
const roundChangedFilesSnapshot = options.normalizeLineEndings
|
|
48102
48990
|
? await captureChangedFilesSnapshot(process.cwd())
|
|
48103
48991
|
: undefined;
|
|
48104
48992
|
try {
|
|
48105
|
-
|
|
48993
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.startCapturingAgentOutput();
|
|
48994
|
+
const result = await runPromptWithTestFeedback({
|
|
48995
|
+
runner,
|
|
48106
48996
|
prompt: codexPrompt,
|
|
48107
48997
|
scriptPath,
|
|
48108
48998
|
projectPath: process.cwd(),
|
|
48999
|
+
promptLabel,
|
|
49000
|
+
testCommand: options.testCommand,
|
|
49001
|
+
onAttemptStarted: (nextAttemptCount) => {
|
|
49002
|
+
attemptCount = nextAttemptCount;
|
|
49003
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(nextAttemptCount);
|
|
49004
|
+
if (nextAttemptCount > 1) {
|
|
49005
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Retrying (attempt ${nextAttemptCount})`);
|
|
49006
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('verifying');
|
|
49007
|
+
}
|
|
49008
|
+
},
|
|
48109
49009
|
});
|
|
48110
|
-
|
|
49010
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
49011
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Committing changes');
|
|
49012
|
+
markPromptDone(nextPrompt.file, nextPrompt.section, result.usage, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, result.attemptCount);
|
|
48111
49013
|
await writePromptFile(nextPrompt.file);
|
|
48112
49014
|
await normalizeLineEndingsForCurrentRound(options, roundChangedFilesSnapshot);
|
|
48113
49015
|
if (options.waitForUser) {
|
|
49016
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
49017
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Waiting... Press Enter to commit');
|
|
48114
49018
|
printCommitMessage(commitMessage);
|
|
48115
49019
|
await waitForEnter(colors.bgWhite('Press Enter to commit and continue...'));
|
|
49020
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
48116
49021
|
}
|
|
48117
|
-
await commitChanges(commitMessage, {
|
|
49022
|
+
await commitChanges(commitMessage, { autoPush: options.autoPush });
|
|
48118
49023
|
await runPostPromptAutoMigrationIfEnabled(options);
|
|
48119
49024
|
}
|
|
48120
49025
|
catch (error) {
|
|
48121
|
-
|
|
49026
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
49027
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('error');
|
|
49028
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(error instanceof Error ? error.message : String(error));
|
|
49029
|
+
markPromptFailed(nextPrompt.file, nextPrompt.section, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, attemptCount);
|
|
48122
49030
|
await writePromptFile(nextPrompt.file);
|
|
48123
49031
|
await writePromptErrorLog({
|
|
48124
49032
|
file: nextPrompt.file,
|
|
@@ -48134,6 +49042,7 @@ async function runCodexPrompts(providedOptions) {
|
|
|
48134
49042
|
}
|
|
48135
49043
|
finally {
|
|
48136
49044
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.stop();
|
|
49045
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.cleanup();
|
|
48137
49046
|
if (!options.dryRun) {
|
|
48138
49047
|
printAgentGitIdentityTipIfNeeded();
|
|
48139
49048
|
}
|
|
@@ -49756,7 +50665,7 @@ function promptbookifyAiText(text) {
|
|
|
49756
50665
|
/**
|
|
49757
50666
|
* Constant for default agent kit model name.
|
|
49758
50667
|
*/
|
|
49759
|
-
const DEFAULT_AGENT_KIT_MODEL_NAME = 'gpt-5.4-
|
|
50668
|
+
const DEFAULT_AGENT_KIT_MODEL_NAME = 'gpt-5.4-mini';
|
|
49760
50669
|
/**
|
|
49761
50670
|
* Creates one structured log entry for streamed tool-call updates.
|
|
49762
50671
|
*
|
|
@@ -50806,6 +51715,7 @@ class AgentLlmExecutionTools {
|
|
|
50806
51715
|
* @param agentSource The agent source string that defines the agent's behavior
|
|
50807
51716
|
*/
|
|
50808
51717
|
constructor(options) {
|
|
51718
|
+
var _a;
|
|
50809
51719
|
this.options = options;
|
|
50810
51720
|
/**
|
|
50811
51721
|
* Cached model requirements to avoid re-parsing the agent source
|
|
@@ -50815,6 +51725,7 @@ class AgentLlmExecutionTools {
|
|
|
50815
51725
|
* Cached parsed agent information
|
|
50816
51726
|
*/
|
|
50817
51727
|
this._cachedAgentInfo = null;
|
|
51728
|
+
this.precomputedModelRequirements = (_a = options.precomputedModelRequirements) !== null && _a !== void 0 ? _a : null;
|
|
50818
51729
|
}
|
|
50819
51730
|
/**
|
|
50820
51731
|
* Updates the agent source and clears the cache
|
|
@@ -50822,9 +51733,13 @@ class AgentLlmExecutionTools {
|
|
|
50822
51733
|
* @param agentSource The new agent source string
|
|
50823
51734
|
*/
|
|
50824
51735
|
updateAgentSource(agentSource) {
|
|
51736
|
+
if (this.options.agentSource === agentSource) {
|
|
51737
|
+
return;
|
|
51738
|
+
}
|
|
50825
51739
|
this.options.agentSource = agentSource;
|
|
50826
51740
|
this._cachedAgentInfo = null;
|
|
50827
51741
|
this._cachedModelRequirements = null;
|
|
51742
|
+
this.precomputedModelRequirements = null;
|
|
50828
51743
|
}
|
|
50829
51744
|
/**
|
|
50830
51745
|
* Get cached or parse agent information
|
|
@@ -50841,6 +51756,16 @@ class AgentLlmExecutionTools {
|
|
|
50841
51756
|
* Note: [🐤] This is names `getModelRequirements` *(not `getAgentModelRequirements`)* because in future these two will be united
|
|
50842
51757
|
*/
|
|
50843
51758
|
async getModelRequirements() {
|
|
51759
|
+
var _a, _b;
|
|
51760
|
+
if (this.precomputedModelRequirements !== null) {
|
|
51761
|
+
if (this.options.isVerbose) {
|
|
51762
|
+
console.info('[🤰]', 'Using precomputed agent model requirements', {
|
|
51763
|
+
agent: this.title,
|
|
51764
|
+
toolCount: (_b = (_a = this.precomputedModelRequirements.tools) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0,
|
|
51765
|
+
});
|
|
51766
|
+
}
|
|
51767
|
+
return this.precomputedModelRequirements;
|
|
51768
|
+
}
|
|
50844
51769
|
if (this._cachedModelRequirements === null) {
|
|
50845
51770
|
const preparationStartedAtMs = Date.now();
|
|
50846
51771
|
if (this.options.isVerbose) {
|
|
@@ -50950,6 +51875,7 @@ class AgentLlmExecutionTools {
|
|
|
50950
51875
|
* Resolves agent requirements, attachments, and runtime overrides into one forwarded chat prompt.
|
|
50951
51876
|
*/
|
|
50952
51877
|
async prepareChatPrompt(prompt) {
|
|
51878
|
+
var _a;
|
|
50953
51879
|
const chatPrompt = this.requireChatPrompt(prompt);
|
|
50954
51880
|
const { sanitizedRequirements, promptSuffix } = await this.getSanitizedAgentModelRequirements();
|
|
50955
51881
|
const attachments = normalizeChatAttachments(chatPrompt.attachments);
|
|
@@ -50967,7 +51893,16 @@ class AgentLlmExecutionTools {
|
|
|
50967
51893
|
mergedTools,
|
|
50968
51894
|
knowledgeSourcesForAgent,
|
|
50969
51895
|
});
|
|
50970
|
-
|
|
51896
|
+
if (this.options.isVerbose) {
|
|
51897
|
+
console.info('[🤰]', 'Prepared agent chat prompt', {
|
|
51898
|
+
agent: this.title,
|
|
51899
|
+
usedPrecomputedModelRequirements: this.precomputedModelRequirements !== null,
|
|
51900
|
+
toolNames: mergedTools.map((tool) => tool.name),
|
|
51901
|
+
knowledgeSourcesCount: (_a = knowledgeSourcesForAgent === null || knowledgeSourcesForAgent === void 0 ? void 0 : knowledgeSourcesForAgent.length) !== null && _a !== void 0 ? _a : 0,
|
|
51902
|
+
promptSuffixLength: promptSuffix.length,
|
|
51903
|
+
systemMessageLength: sanitizedRequirements.systemMessage.length,
|
|
51904
|
+
});
|
|
51905
|
+
}
|
|
50971
51906
|
return {
|
|
50972
51907
|
forwardedPrompt,
|
|
50973
51908
|
sanitizedRequirements,
|
|
@@ -51154,6 +52089,7 @@ class AgentLlmExecutionTools {
|
|
|
51154
52089
|
* Runs one prepared prompt through the deprecated OpenAI Assistant backend.
|
|
51155
52090
|
*/
|
|
51156
52091
|
async callOpenAiAssistantChatModelStream(options) {
|
|
52092
|
+
var _a, _b, _c, _d;
|
|
51157
52093
|
const assistant = await this.getOrPrepareOpenAiAssistant({
|
|
51158
52094
|
llmTools: options.llmTools,
|
|
51159
52095
|
originalPrompt: options.originalPrompt,
|
|
@@ -51161,7 +52097,14 @@ class AgentLlmExecutionTools {
|
|
|
51161
52097
|
onProgress: options.onProgress,
|
|
51162
52098
|
});
|
|
51163
52099
|
const promptWithAgentModelRequirementsForOpenAiAssistantExecutionTools = createOpenAiAssistantPrompt(options.preparedChatPrompt.forwardedPrompt);
|
|
51164
|
-
|
|
52100
|
+
if (this.options.isVerbose) {
|
|
52101
|
+
console.info('[🤰]', 'Prepared OpenAI Assistant prompt', {
|
|
52102
|
+
agent: this.title,
|
|
52103
|
+
toolNames: (_b = (_a = promptWithAgentModelRequirementsForOpenAiAssistantExecutionTools.modelRequirements.tools) === null || _a === void 0 ? void 0 : _a.map((tool) => tool.name)) !== null && _b !== void 0 ? _b : [],
|
|
52104
|
+
knowledgeSourcesCount: (_d = (_c = promptWithAgentModelRequirementsForOpenAiAssistantExecutionTools.modelRequirements
|
|
52105
|
+
.knowledgeSources) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0,
|
|
52106
|
+
});
|
|
52107
|
+
}
|
|
51165
52108
|
return assistant.callChatModelStream(promptWithAgentModelRequirementsForOpenAiAssistantExecutionTools, options.onProgress, options.streamOptions);
|
|
51166
52109
|
}
|
|
51167
52110
|
/**
|
|
@@ -51852,7 +52795,8 @@ class Agent extends AgentLlmExecutionTools {
|
|
|
51852
52795
|
isVerbose: options.isVerbose,
|
|
51853
52796
|
llmTools: getSingleLlmExecutionTools(options.executionTools.llm),
|
|
51854
52797
|
assistantPreparationMode: options.assistantPreparationMode,
|
|
51855
|
-
agentSource: agentSource.value,
|
|
52798
|
+
agentSource: agentSource.value,
|
|
52799
|
+
precomputedModelRequirements: options.precomputedModelRequirements,
|
|
51856
52800
|
});
|
|
51857
52801
|
this._agentName = undefined;
|
|
51858
52802
|
/**
|