@promptbook/node 0.114.0-11 → 0.114.0-13
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 +459 -133
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +22 -4
- package/esm/scripts/run-agent-messages/messages/buildAgentMessagePrompt.d.ts +3 -3
- package/esm/scripts/run-codex-prompts/common/runGoScript/$spawnLoggedBashScript.d.ts +25 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/$terminateLoggedBashProcessTree.d.ts +11 -0
- package/esm/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +4 -0
- package/esm/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +5 -0
- package/esm/src/book-2.0/agent-source/ParsedUnknownCommitment.d.ts +26 -0
- package/esm/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.unknown.test.d.ts +1 -0
- package/esm/src/book-2.0/agent-source/getBookCommitmentLineType.d.ts +19 -0
- package/esm/src/book-2.0/agent-source/parseAgentSourceWithCommitments.unknown.test.d.ts +1 -0
- package/esm/src/book-3.0/AgentMessageRunReport.d.ts +28 -0
- package/esm/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +94 -0
- package/esm/src/book-3.0/AgentPlannedMessagesSidecar.test.d.ts +1 -0
- package/esm/src/book-3.0/createAgentMessageSidecarBaseName.d.ts +13 -0
- package/esm/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.d.ts +28 -0
- package/esm/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.test.d.ts +1 -0
- package/esm/src/book-components/Chat/utils/agentProjectToolCall.d.ts +46 -0
- package/esm/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +24 -0
- package/esm/src/cli/cli-commands/common/harness/$checkHarnessInstallation.d.ts +3 -3
- package/esm/src/cli/cli-commands/common/harness/$checkHarnessInstallation.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -3
- package/esm/src/cli/cli-commands/common/harness/HarnessInstallationStatus.d.ts +3 -2
- package/esm/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +29 -0
- package/esm/src/cli/cli-commands/common/harnessUpdateCliOptions.test.d.ts +1 -0
- package/esm/src/executables/platforms/locateAppOnWindows.d.ts +1 -1
- package/esm/src/executables/platforms/locateAppOnWindows.test.d.ts +1 -0
- package/esm/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +59 -0
- package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.d.ts +19 -0
- package/esm/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.test.d.ts +1 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +2 -2
- package/umd/index.umd.js +457 -131
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-agent-messages/messages/buildAgentGoalChatPromptSection.d.ts +22 -4
- package/umd/scripts/run-agent-messages/messages/buildAgentMessagePrompt.d.ts +3 -3
- package/umd/scripts/run-codex-prompts/common/runGoScript/$spawnLoggedBashScript.d.ts +25 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/$terminateLoggedBashProcessTree.d.ts +11 -0
- package/umd/scripts/run-codex-prompts/common/runGoScript/scriptExecutionLog.d.ts +4 -0
- package/umd/src/book-2.0/agent-source/AgentSourceParseResult.d.ts +5 -0
- package/umd/src/book-2.0/agent-source/ParsedUnknownCommitment.d.ts +26 -0
- package/umd/src/book-2.0/agent-source/createAgentModelRequirementsWithCommitments.unknown.test.d.ts +1 -0
- package/umd/src/book-2.0/agent-source/getBookCommitmentLineType.d.ts +19 -0
- package/umd/src/book-2.0/agent-source/parseAgentSourceWithCommitments.unknown.test.d.ts +1 -0
- package/umd/src/book-3.0/AgentMessageRunReport.d.ts +28 -0
- package/umd/src/book-3.0/AgentPlannedMessagesSidecar.d.ts +94 -0
- package/umd/src/book-3.0/AgentPlannedMessagesSidecar.test.d.ts +1 -0
- package/umd/src/book-3.0/createAgentMessageSidecarBaseName.d.ts +13 -0
- package/umd/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.d.ts +28 -0
- package/umd/src/book-components/BookEditor/createUnknownCommitmentDiagnostics.test.d.ts +1 -0
- package/umd/src/book-components/Chat/utils/agentProjectToolCall.d.ts +46 -0
- package/umd/src/book-components/Chat/utils/timeoutToolCallPresentation.d.ts +24 -0
- package/umd/src/cli/cli-commands/common/harness/$checkHarnessInstallation.d.ts +3 -3
- package/umd/src/cli/cli-commands/common/harness/$checkHarnessInstallation.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/harness/$ensureHarnessInstallations.d.ts +3 -3
- package/umd/src/cli/cli-commands/common/harness/HarnessInstallationStatus.d.ts +3 -2
- package/umd/src/cli/cli-commands/common/harnessUpdateCliOptions.d.ts +29 -0
- package/umd/src/cli/cli-commands/common/harnessUpdateCliOptions.test.d.ts +1 -0
- package/umd/src/executables/platforms/locateAppOnWindows.d.ts +1 -1
- package/umd/src/executables/platforms/locateAppOnWindows.test.d.ts +1 -0
- package/umd/src/utils/agent-message-runtime/parseAgentMessageRuntimeLogEvents.d.ts +59 -0
- package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.d.ts +19 -0
- package/umd/src/utils/agent-message-runtime/resolveAgentMessageTouchedProjectNames.test.d.ts +1 -0
- package/umd/src/version.d.ts +1 -1
- package/esm/apps/agents-server/src/utils/agentGoalChat/agentGoalChatConstants.d.ts +0 -12
- package/esm/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeConstants.d.ts +0 -40
- package/umd/apps/agents-server/src/utils/agentGoalChat/agentGoalChatConstants.d.ts +0 -12
- package/umd/apps/agents-server/src/utils/agentProjects/agentProjectRuntimeConstants.d.ts +0 -40
package/umd/index.umd.js
CHANGED
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* @generated
|
|
48
48
|
* @see https://github.com/webgptorg/promptbook
|
|
49
49
|
*/
|
|
50
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-
|
|
50
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.114.0-13';
|
|
51
51
|
/**
|
|
52
52
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
53
53
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -2954,14 +2954,90 @@
|
|
|
2954
2954
|
* without the generated script and the prompt it embeds.
|
|
2955
2955
|
*/
|
|
2956
2956
|
const SCRIPT_EXECUTION_LOG_RAW_OUTPUT_MARKER = '--- raw output ---';
|
|
2957
|
+
/**
|
|
2958
|
+
* Command which terminates the Bash process tree rooted at the running harness.
|
|
2959
|
+
*
|
|
2960
|
+
* Bash's POSIX process IDs differ from Windows process IDs in Git Bash, so the Windows branch resolves the native PID
|
|
2961
|
+
* before delegating to `taskkill`. Unix harnesses run in a dedicated Bash job process group, which can be terminated
|
|
2962
|
+
* with its negative process ID.
|
|
2963
|
+
*/
|
|
2964
|
+
const TERMINATE_BASH_PROCESS_TREE_COMMAND = process.platform === 'win32'
|
|
2965
|
+
? _spaceTrim.spaceTrim(`
|
|
2966
|
+
HARNESS_WINDOWS_PROCESS_ID="$(ps -l -p "$HARNESS_PROCESS_ID" | awk 'NR == 2 { print $4 }')"
|
|
2967
|
+
if [ -n "$HARNESS_WINDOWS_PROCESS_ID" ]; then
|
|
2968
|
+
MSYS_NO_PATHCONV=1 taskkill.exe /PID "$HARNESS_WINDOWS_PROCESS_ID" /T /F > /dev/null 2>&1 || true
|
|
2969
|
+
fi
|
|
2970
|
+
`)
|
|
2971
|
+
: 'kill -TERM -- "-$HARNESS_PROCESS_ID" 2>/dev/null || true';
|
|
2972
|
+
/**
|
|
2973
|
+
* Shell condition that detects whether the Node process which owns the harness is still running.
|
|
2974
|
+
*
|
|
2975
|
+
* Git Bash translates process IDs and command switches, so querying the native Windows PID needs both `tasklist` and
|
|
2976
|
+
* disabled MSYS path conversion there. Unix can use the native `kill -0` process existence check.
|
|
2977
|
+
*/
|
|
2978
|
+
const IS_PARENT_PROCESS_RUNNING_CONDITION = process.platform === 'win32'
|
|
2979
|
+
? 'MSYS_NO_PATHCONV=1 tasklist.exe /FI "PID eq $PARENT_CODER_PROCESS_ID" /NH | awk -v processId="$PARENT_CODER_PROCESS_ID" \'$2 == processId { isFound = 1 } END { exit isFound ? 0 : 1 }\''
|
|
2980
|
+
: 'kill -0 "$PARENT_CODER_PROCESS_ID" 2>/dev/null';
|
|
2981
|
+
/**
|
|
2982
|
+
* Environment variable that identifies the Node process responsible for a temporary harness shell.
|
|
2983
|
+
*/
|
|
2984
|
+
const PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME = 'PTBK_CODER_PARENT_PROCESS_ID';
|
|
2957
2985
|
/**
|
|
2958
2986
|
* Small bash wrapper that preserves stdout/stderr streams while teeing both into the runtime log file.
|
|
2987
|
+
*
|
|
2988
|
+
* A watcher polls the owning Node process by its PID. If that process exits abruptly, the watcher stops the whole
|
|
2989
|
+
* Bash and harness process tree instead of letting it continue as an orphan.
|
|
2959
2990
|
*/
|
|
2960
2991
|
const LOGGED_BASH_WRAPPER_COMMAND = _spaceTrim.spaceTrim(`
|
|
2992
|
+
PARENT_CODER_PROCESS_ID="\${${PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME}}"
|
|
2993
|
+
unset ${PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME}
|
|
2994
|
+
|
|
2995
|
+
terminate_harness_process_tree() {
|
|
2996
|
+
# Keep the EXIT cleanup intact so the wrapper can also stop its parent-process watcher.
|
|
2997
|
+
trap - HUP INT TERM
|
|
2998
|
+
${TERMINATE_BASH_PROCESS_TREE_COMMAND}
|
|
2999
|
+
}
|
|
3000
|
+
|
|
3001
|
+
is_parent_process_running() {
|
|
3002
|
+
${IS_PARENT_PROCESS_RUNNING_CONDITION}
|
|
3003
|
+
}
|
|
3004
|
+
|
|
2961
3005
|
if [ -n "\${${PTBK_CODER_LOG_FILE_ENV_NAME}:-}" ]; then
|
|
2962
|
-
exec > >(tee -a "
|
|
3006
|
+
exec > >(tee -a "$${PTBK_CODER_LOG_FILE_ENV_NAME}") 2> >(tee -a "$${PTBK_CODER_LOG_FILE_ENV_NAME}" >&2)
|
|
3007
|
+
fi
|
|
3008
|
+
|
|
3009
|
+
watch_parent_process() {
|
|
3010
|
+
trap 'exit 0' HUP INT TERM
|
|
3011
|
+
|
|
3012
|
+
while is_parent_process_running; do
|
|
3013
|
+
sleep 1
|
|
3014
|
+
done
|
|
3015
|
+
|
|
3016
|
+
terminate_harness_process_tree
|
|
3017
|
+
}
|
|
3018
|
+
|
|
3019
|
+
# Background harness jobs need their own process group on Unix so termination cannot reach the parent coder.
|
|
3020
|
+
set -m
|
|
3021
|
+
if ! is_parent_process_running; then
|
|
3022
|
+
exit 1
|
|
2963
3023
|
fi
|
|
2964
|
-
bash "$1"
|
|
3024
|
+
bash "$1" &
|
|
3025
|
+
HARNESS_PROCESS_ID=$!
|
|
3026
|
+
|
|
3027
|
+
cleanup_parent_process_watcher() {
|
|
3028
|
+
kill "$PARENT_PROCESS_WATCHER_PID" 2>/dev/null || true
|
|
3029
|
+
wait "$PARENT_PROCESS_WATCHER_PID" 2>/dev/null || true
|
|
3030
|
+
}
|
|
3031
|
+
|
|
3032
|
+
watch_parent_process &
|
|
3033
|
+
PARENT_PROCESS_WATCHER_PID=$!
|
|
3034
|
+
|
|
3035
|
+
trap cleanup_parent_process_watcher EXIT
|
|
3036
|
+
trap terminate_harness_process_tree HUP INT TERM
|
|
3037
|
+
|
|
3038
|
+
wait "$HARNESS_PROCESS_ID"
|
|
3039
|
+
SCRIPT_EXIT_CODE=$?
|
|
3040
|
+
exit "$SCRIPT_EXIT_CODE"
|
|
2965
3041
|
`);
|
|
2966
3042
|
/**
|
|
2967
3043
|
* Shapes one bash invocation that optionally mirrors live script output into a temporary log file.
|
|
@@ -3017,6 +3093,38 @@
|
|
|
3017
3093
|
return scriptPath.toLowerCase().endsWith('.test.sh') ? 'test shell' : 'runner shell';
|
|
3018
3094
|
}
|
|
3019
3095
|
|
|
3096
|
+
/**
|
|
3097
|
+
* Standard streams used by every temporary Bash runner.
|
|
3098
|
+
*/
|
|
3099
|
+
const BASH_PROCESS_STDIO = ['pipe', 'pipe', 'pipe'];
|
|
3100
|
+
/**
|
|
3101
|
+
* Whether the current Node process is running on Windows.
|
|
3102
|
+
*/
|
|
3103
|
+
const IS_WINDOWS$1 = process.platform === 'win32';
|
|
3104
|
+
/**
|
|
3105
|
+
* Starts one temporary Bash script in a process tree owned by the current Node process.
|
|
3106
|
+
*
|
|
3107
|
+
* The wrapper watches the supplied owning process ID. When that process exits abruptly, the wrapper terminates every
|
|
3108
|
+
* nested shell and harness process instead of leaving it orphaned.
|
|
3109
|
+
*
|
|
3110
|
+
* @private internal utility of the coding prompt runner
|
|
3111
|
+
*/
|
|
3112
|
+
function $spawnLoggedBashScript(options) {
|
|
3113
|
+
var _a;
|
|
3114
|
+
const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
|
|
3115
|
+
const parentProcessId = (_a = options.parentProcessId) !== null && _a !== void 0 ? _a : process.pid;
|
|
3116
|
+
return child_process.spawn('bash', bashExecution.args, {
|
|
3117
|
+
detached: !IS_WINDOWS$1,
|
|
3118
|
+
env: {
|
|
3119
|
+
...process.env,
|
|
3120
|
+
...bashExecution.env,
|
|
3121
|
+
[PTBK_CODER_PARENT_PROCESS_ID_ENV_NAME]: parentProcessId.toString(),
|
|
3122
|
+
},
|
|
3123
|
+
stdio: BASH_PROCESS_STDIO,
|
|
3124
|
+
windowsHide: true,
|
|
3125
|
+
});
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3020
3128
|
/**
|
|
3021
3129
|
* Prints one live shell output chunk to the terminal when console mirroring is enabled.
|
|
3022
3130
|
*/
|
|
@@ -3039,12 +3147,12 @@
|
|
|
3039
3147
|
async function runBashScriptWithOutput(options) {
|
|
3040
3148
|
var _a;
|
|
3041
3149
|
await appendScriptExecutionLogStart(options);
|
|
3042
|
-
const bashExecution = buildLoggedBashExecution(options.scriptPath, options.logPath);
|
|
3043
3150
|
const scriptPathPosix = toPosixPath(options.scriptPath);
|
|
3044
3151
|
const shouldPrintLiveOutput = (_a = options.shouldPrintLiveOutput) !== null && _a !== void 0 ? _a : true;
|
|
3045
3152
|
return await new Promise((resolve, reject) => {
|
|
3046
|
-
const commandProcess =
|
|
3047
|
-
|
|
3153
|
+
const commandProcess = $spawnLoggedBashScript({
|
|
3154
|
+
scriptPath: options.scriptPath,
|
|
3155
|
+
logPath: options.logPath,
|
|
3048
3156
|
});
|
|
3049
3157
|
let output = '';
|
|
3050
3158
|
let settled = false;
|
|
@@ -3103,8 +3211,9 @@
|
|
|
3103
3211
|
const failure = new Error(_spaceTrim.spaceTrim(output) || `Command "bash ${scriptPathPosix}" exited with code ${code}`);
|
|
3104
3212
|
settleWithLog(`failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`, () => reject(failure), failure);
|
|
3105
3213
|
};
|
|
3214
|
+
// Wait for `close`, not only `exit`, because the Bash wrapper can still be flushing its tee process
|
|
3215
|
+
// substitutions after the direct shell exits.
|
|
3106
3216
|
commandProcess.on('close', handleExit);
|
|
3107
|
-
commandProcess.on('exit', handleExit);
|
|
3108
3217
|
commandProcess.on('disconnect', () => {
|
|
3109
3218
|
const failure = new Error(`Command "bash ${scriptPathPosix}" disconnected`);
|
|
3110
3219
|
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
@@ -3971,6 +4080,35 @@
|
|
|
3971
4080
|
error.message.includes('bin/node'));
|
|
3972
4081
|
}
|
|
3973
4082
|
|
|
4083
|
+
/**
|
|
4084
|
+
* Whether the current coder process runs on Windows.
|
|
4085
|
+
*/
|
|
4086
|
+
const IS_WINDOWS = process.platform === 'win32';
|
|
4087
|
+
/**
|
|
4088
|
+
* Stops one active temporary Bash shell together with the harness process tree it owns.
|
|
4089
|
+
*
|
|
4090
|
+
* Unix sends `SIGTERM` to the wrapper so its shell trap terminates the separately grouped harness job. Windows does
|
|
4091
|
+
* not reliably deliver that signal to Bash, so the native `taskkill` command terminates the direct shell tree instead.
|
|
4092
|
+
*
|
|
4093
|
+
* @private internal utility of the coding prompt runner
|
|
4094
|
+
*/
|
|
4095
|
+
function $terminateLoggedBashProcessTree(commandProcess) {
|
|
4096
|
+
if (commandProcess.exitCode !== null || commandProcess.signalCode !== null) {
|
|
4097
|
+
return;
|
|
4098
|
+
}
|
|
4099
|
+
if (!IS_WINDOWS) {
|
|
4100
|
+
commandProcess.kill('SIGTERM');
|
|
4101
|
+
return;
|
|
4102
|
+
}
|
|
4103
|
+
if (!commandProcess.pid) {
|
|
4104
|
+
return;
|
|
4105
|
+
}
|
|
4106
|
+
child_process.spawnSync('taskkill.exe', ['/PID', commandProcess.pid.toString(), '/T', '/F'], {
|
|
4107
|
+
stdio: 'ignore',
|
|
4108
|
+
windowsHide: true,
|
|
4109
|
+
});
|
|
4110
|
+
}
|
|
4111
|
+
|
|
3974
4112
|
/**
|
|
3975
4113
|
* Maximum number of output characters included in thrown error messages.
|
|
3976
4114
|
*/
|
|
@@ -4013,15 +4151,16 @@
|
|
|
4013
4151
|
const scriptPathPosix = toPosixPath(scriptPath);
|
|
4014
4152
|
const shouldPrintLiveOutput = (_a = options.shouldPrintLiveOutput) !== null && _a !== void 0 ? _a : true;
|
|
4015
4153
|
await appendScriptExecutionLogStart(options);
|
|
4016
|
-
const bashExecution = buildLoggedBashExecution(scriptPath, options.logPath);
|
|
4017
4154
|
return await new Promise((resolve, reject) => {
|
|
4018
|
-
const commandProcess =
|
|
4019
|
-
|
|
4155
|
+
const commandProcess = $spawnLoggedBashScript({
|
|
4156
|
+
scriptPath,
|
|
4157
|
+
logPath: options.logPath,
|
|
4020
4158
|
});
|
|
4021
4159
|
let stdoutBuffer = '';
|
|
4022
4160
|
let stderrBuffer = '';
|
|
4023
4161
|
let fullOutput = '';
|
|
4024
4162
|
let markerSeen = false;
|
|
4163
|
+
let isCompletedAfterIdleTimeout = false;
|
|
4025
4164
|
let idleTimer;
|
|
4026
4165
|
let settled = false;
|
|
4027
4166
|
let isSettling = false;
|
|
@@ -4063,15 +4202,16 @@
|
|
|
4063
4202
|
});
|
|
4064
4203
|
};
|
|
4065
4204
|
/**
|
|
4066
|
-
*
|
|
4205
|
+
* Stops a marker-completed process tree after its trailing output becomes idle.
|
|
4067
4206
|
*/
|
|
4068
4207
|
const finishAfterIdleTimeout = () => {
|
|
4069
|
-
|
|
4208
|
+
isCompletedAfterIdleTimeout = true;
|
|
4209
|
+
idleTimer = undefined;
|
|
4070
4210
|
try {
|
|
4071
|
-
commandProcess
|
|
4211
|
+
$terminateLoggedBashProcessTree(commandProcess);
|
|
4072
4212
|
}
|
|
4073
4213
|
catch (_a) {
|
|
4074
|
-
//
|
|
4214
|
+
// The close handler below still settles normally when Bash already exited before the idle timer fired.
|
|
4075
4215
|
}
|
|
4076
4216
|
};
|
|
4077
4217
|
/**
|
|
@@ -4130,7 +4270,11 @@
|
|
|
4130
4270
|
const failure = code === 0 || markerSeen
|
|
4131
4271
|
? undefined
|
|
4132
4272
|
: new Error(buildCommandFailureMessage(scriptPathPosix, code, fullOutput));
|
|
4133
|
-
const status =
|
|
4273
|
+
const status = isCompletedAfterIdleTimeout
|
|
4274
|
+
? 'completed after idle timeout'
|
|
4275
|
+
: failure
|
|
4276
|
+
? `failed with exit code ${code !== null && code !== void 0 ? code : 'unknown'}`
|
|
4277
|
+
: 'succeeded';
|
|
4134
4278
|
settleWithLog(status, () => {
|
|
4135
4279
|
if (!failure) {
|
|
4136
4280
|
resolve(fullOutput);
|
|
@@ -4139,8 +4283,9 @@
|
|
|
4139
4283
|
reject(failure);
|
|
4140
4284
|
});
|
|
4141
4285
|
};
|
|
4286
|
+
// Wait for `close`, not only `exit`, because the Bash wrapper can still be flushing its tee process
|
|
4287
|
+
// substitutions after the direct shell exits.
|
|
4142
4288
|
commandProcess.on('close', handleExit);
|
|
4143
|
-
commandProcess.on('exit', handleExit);
|
|
4144
4289
|
commandProcess.on('disconnect', () => {
|
|
4145
4290
|
const failure = new Error(buildCommandFailureMessage(scriptPathPosix, null, fullOutput));
|
|
4146
4291
|
settleWithLog('failed after disconnect', () => reject(failure), failure);
|
|
@@ -5093,7 +5238,7 @@
|
|
|
5093
5238
|
- You have 100% control over every project folder: create, read, modify, and delete files there, run scripts and commands inside it, and keep any persistent data you need between conversations.
|
|
5094
5239
|
- When the user asks you to build something (for example a website) or to do longer-term work, create a new project folder \`${AGENT_PROJECTS_DIRECTORY_PATH}/<project-name>/\` (use a short kebab-case name) and do the work inside it. Modify an existing project when the user refers to work you already did.
|
|
5095
5240
|
- A project can be a git repository — you can run \`git init\` inside a project folder and commit your work there.
|
|
5096
|
-
- Do not touch anything outside the \`${AGENT_PROJECTS_DIRECTORY_PATH}/\` directory
|
|
5241
|
+
- Do not touch anything outside the \`${AGENT_PROJECTS_DIRECTORY_PATH}/\` directory beyond the file changes allowed at the top of this prompt.
|
|
5097
5242
|
|
|
5098
5243
|
${block(buildProjectReferenceInstructions(projectsUrlPath))}
|
|
5099
5244
|
${block(buildProjectRuntimeInstructions(options.projectRuntimeApi))}
|
|
@@ -5149,63 +5294,148 @@
|
|
|
5149
5294
|
}
|
|
5150
5295
|
|
|
5151
5296
|
/**
|
|
5152
|
-
*
|
|
5297
|
+
* Milliseconds in one second.
|
|
5298
|
+
*
|
|
5299
|
+
* @private internal timeout-chat constant
|
|
5153
5300
|
*/
|
|
5301
|
+
const SECOND_IN_MILLISECONDS = 1000;
|
|
5154
5302
|
/**
|
|
5155
|
-
*
|
|
5303
|
+
* Seconds in one minute.
|
|
5304
|
+
*
|
|
5305
|
+
* @private internal timeout-chat constant
|
|
5156
5306
|
*/
|
|
5157
|
-
const
|
|
5158
|
-
|
|
5307
|
+
const MINUTE_IN_SECONDS = 60;
|
|
5159
5308
|
/**
|
|
5160
|
-
*
|
|
5309
|
+
* Seconds in one hour.
|
|
5310
|
+
*
|
|
5311
|
+
* @private internal timeout-chat constant
|
|
5312
|
+
*/
|
|
5313
|
+
const HOUR_IN_SECONDS = 60 * MINUTE_IN_SECONDS;
|
|
5314
|
+
/**
|
|
5315
|
+
* Seconds in one day.
|
|
5316
|
+
*
|
|
5317
|
+
* @private internal timeout-chat constant
|
|
5318
|
+
*/
|
|
5319
|
+
const HOURS_IN_DAY = 24;
|
|
5320
|
+
/**
|
|
5321
|
+
* Seconds in one day.
|
|
5322
|
+
*
|
|
5323
|
+
* @private internal timeout-chat constant
|
|
5161
5324
|
*/
|
|
5325
|
+
const DAY_IN_SECONDS = HOURS_IN_DAY * HOUR_IN_SECONDS;
|
|
5162
5326
|
/**
|
|
5163
|
-
*
|
|
5327
|
+
* Converts timeout duration into natural language sentence fragments.
|
|
5328
|
+
*
|
|
5329
|
+
* Shared by every timeout surface: the chat chips, the goal-chat planned messages of the Agents
|
|
5330
|
+
* Server, and the planned-message prompt section of the agent-folder runner.
|
|
5331
|
+
*
|
|
5332
|
+
* @param milliseconds - Duration or repeat interval in milliseconds.
|
|
5333
|
+
* @returns Label such as `5 minutes` or `1 hour 30 minutes`.
|
|
5334
|
+
*
|
|
5335
|
+
* @private internal utility of `<Chat/>` and the Agents Server planned messages
|
|
5164
5336
|
*/
|
|
5165
|
-
|
|
5337
|
+
function formatTimeoutDurationHuman(milliseconds) {
|
|
5338
|
+
const normalizedMilliseconds = Math.max(0, Math.floor(milliseconds));
|
|
5339
|
+
const totalSeconds = Math.max(1, Math.floor(normalizedMilliseconds / SECOND_IN_MILLISECONDS));
|
|
5340
|
+
if (totalSeconds < MINUTE_IN_SECONDS) {
|
|
5341
|
+
return formatTimeoutUnit(totalSeconds, 'second');
|
|
5342
|
+
}
|
|
5343
|
+
if (totalSeconds < HOUR_IN_SECONDS) {
|
|
5344
|
+
const roundedMinutes = Math.max(1, Math.round(totalSeconds / MINUTE_IN_SECONDS));
|
|
5345
|
+
return formatTimeoutUnit(roundedMinutes, 'minute');
|
|
5346
|
+
}
|
|
5347
|
+
if (totalSeconds < DAY_IN_SECONDS) {
|
|
5348
|
+
const hours = Math.floor(totalSeconds / HOUR_IN_SECONDS);
|
|
5349
|
+
const minutes = Math.floor((totalSeconds % HOUR_IN_SECONDS) / MINUTE_IN_SECONDS);
|
|
5350
|
+
if (minutes === 0) {
|
|
5351
|
+
return formatTimeoutUnit(hours, 'hour');
|
|
5352
|
+
}
|
|
5353
|
+
return `${formatTimeoutUnit(hours, 'hour')} ${formatTimeoutUnit(minutes, 'minute')}`;
|
|
5354
|
+
}
|
|
5355
|
+
const days = Math.floor(totalSeconds / DAY_IN_SECONDS);
|
|
5356
|
+
const hours = Math.floor((totalSeconds % DAY_IN_SECONDS) / HOUR_IN_SECONDS);
|
|
5357
|
+
if (hours === 0) {
|
|
5358
|
+
return formatTimeoutUnit(days, 'day');
|
|
5359
|
+
}
|
|
5360
|
+
return `${formatTimeoutUnit(days, 'day')} ${formatTimeoutUnit(hours, 'hour')}`;
|
|
5361
|
+
}
|
|
5362
|
+
/**
|
|
5363
|
+
* Formats one pluralized timeout unit.
|
|
5364
|
+
*
|
|
5365
|
+
* @private internal timeout-chat helper
|
|
5366
|
+
*/
|
|
5367
|
+
function formatTimeoutUnit(value, unit) {
|
|
5368
|
+
return `${value} ${unit}${value === 1 ? '' : 's'}`;
|
|
5369
|
+
}
|
|
5370
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
5166
5371
|
|
|
5167
5372
|
/**
|
|
5168
5373
|
* Builds the planned-message instructions available to an Agents Server-managed coding agent.
|
|
5169
5374
|
*
|
|
5170
|
-
* Planned messages always target the agent's singleton goal chat, regardless of the chat in which
|
|
5171
|
-
*
|
|
5375
|
+
* Planned messages always target the agent's singleton goal chat, regardless of the chat in which the
|
|
5376
|
+
* wake-up is planned, and they repeat like `setInterval` until they are cancelled. The sidecar file is
|
|
5377
|
+
* the only channel that changes them, so an answer that merely claims a follow-up was planned changes
|
|
5378
|
+
* nothing — and an answer that changes nothing keeps the current plan running.
|
|
5379
|
+
*
|
|
5380
|
+
* @param sidecar - Sidecar prepared by the Agents Server for the answered message.
|
|
5381
|
+
* @returns Prompt section, or an empty string outside Agents Server-managed runs.
|
|
5172
5382
|
*/
|
|
5173
|
-
function buildAgentGoalChatPromptSection(
|
|
5174
|
-
if (!
|
|
5383
|
+
function buildAgentGoalChatPromptSection(sidecar) {
|
|
5384
|
+
if (!sidecar) {
|
|
5175
5385
|
return '';
|
|
5176
5386
|
}
|
|
5177
|
-
return _spaceTrim.spaceTrim(`
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
You can plan a future message that wakes you in your singleton goal chat. These commands are available during every Agents Server-managed chat invocation, not only while answering inside the goal chat.
|
|
5387
|
+
return _spaceTrim.spaceTrim((block) => `
|
|
5388
|
+
## Planned goal-chat messages
|
|
5181
5389
|
|
|
5182
|
-
|
|
5183
|
-
- Use \`set_timeout\` when useful work should resume later. The delay is a positive number of milliseconds and the message should say exactly what your future invocation needs to do.
|
|
5184
|
-
- Use \`cancel_timeout\` with the returned \`timeoutId\` when a planned message is no longer useful.
|
|
5185
|
-
- A fired message appears in the goal chat and invokes you there. If more future work remains, plan the next useful message during that invocation.
|
|
5390
|
+
You can plan a message that repeatedly wakes you in your singleton goal chat. A planned message works like \`setInterval\`, not like \`setTimeout\`: once planned, it keeps waking you at its interval until you cancel it. This works during every Agents Server-managed chat invocation, not only while answering inside the goal chat.
|
|
5186
5391
|
|
|
5187
|
-
|
|
5392
|
+
${block(buildCurrentPlannedMessagesLines(sidecar.currentPlannedMessages))}
|
|
5188
5393
|
|
|
5189
|
-
|
|
5190
|
-
# list_timeouts
|
|
5191
|
-
curl -sS -X POST "$${runtimeApi.serverUrlEnvironmentVariableName}${AGENT_GOAL_CHAT_PLANNED_MESSAGES_INTERNAL_API_PATH}" \\
|
|
5192
|
-
-H "Content-Type: application/json" \\
|
|
5193
|
-
-H "${USER_CHAT_WORKER_TOKEN_HEADER}: $${runtimeApi.tokenEnvironmentVariableName}" \\
|
|
5194
|
-
-d '{"action":"list","agentPermanentId":"${runtimeApi.agentPermanentId}"}'
|
|
5394
|
+
Editing \`${sidecar.relativeSidecarPath}\` is the **only** way to change what wakes you. Writing in your answer that you scheduled something does not schedule anything.
|
|
5195
5395
|
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5396
|
+
- **Keeping your planned messages as they are is the default.** When the list above already matches your goal, leave \`commands\` empty — every listed message keeps repeating on its own, and re-planning it would only duplicate it.
|
|
5397
|
+
- When your goal needs a repeating wake-up that is not listed above, append \`{"action":"set","milliseconds":<repeat interval>,"message":"<what each future invocation must do>"}\` to the \`commands\` array of that file.
|
|
5398
|
+
- When a listed message no longer matches your goal (for example your goal now says every 10 minutes while the message repeats every 5 minutes), append \`{"action":"cancel","timeoutId":"<timeout id>"}\` and one \`set\` command with the interval your goal really requires.
|
|
5399
|
+
- When your goal no longer needs a listed message at all, cancel it without planning a replacement.
|
|
5400
|
+
- Never edit \`version\`, \`agentPermanentId\`, or \`currentPlannedMessages\`.
|
|
5401
|
+
- The Agents Server applies every command once your answer is finished, and each repetition appears in the goal chat and invokes you there.
|
|
5402
|
+
- Only mention a planned follow-up in your answer when it is really planned: either you appended the matching \`set\` command, or you kept one of the messages listed above.
|
|
5403
|
+
`);
|
|
5404
|
+
}
|
|
5405
|
+
/**
|
|
5406
|
+
* Renders the already planned messages so the agent can compare them with its goal.
|
|
5407
|
+
*
|
|
5408
|
+
* @param currentPlannedMessages - Planned messages prepared by the Agents Server.
|
|
5409
|
+
* @returns Markdown list, or a sentence stating that nothing is planned yet.
|
|
5410
|
+
*
|
|
5411
|
+
* @private function of `buildAgentGoalChatPromptSection`
|
|
5412
|
+
*/
|
|
5413
|
+
function buildCurrentPlannedMessagesLines(currentPlannedMessages) {
|
|
5414
|
+
if (currentPlannedMessages.length === 0) {
|
|
5415
|
+
return 'You currently have no planned messages waiting.';
|
|
5416
|
+
}
|
|
5417
|
+
const plannedMessageLines = currentPlannedMessages.map(createCurrentPlannedMessageLine);
|
|
5418
|
+
return _spaceTrim.spaceTrim((block) => `
|
|
5419
|
+
These planned messages are already waiting for you, so keep them unless they stopped matching your goal:
|
|
5201
5420
|
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5421
|
+
${block(plannedMessageLines.join('\n'))}
|
|
5422
|
+
`);
|
|
5423
|
+
}
|
|
5424
|
+
/**
|
|
5425
|
+
* Renders one already planned message with the schedule the agent has to compare with its goal.
|
|
5426
|
+
*
|
|
5427
|
+
* @param plannedMessage - One planned message prepared by the Agents Server.
|
|
5428
|
+
* @returns Markdown list item.
|
|
5429
|
+
*
|
|
5430
|
+
* @private function of `buildAgentGoalChatPromptSection`
|
|
5431
|
+
*/
|
|
5432
|
+
function createCurrentPlannedMessageLine(plannedMessage) {
|
|
5433
|
+
var _a;
|
|
5434
|
+
const message = ((_a = plannedMessage.message) === null || _a === void 0 ? void 0 : _a.trim()) || 'Continue working towards the current goal.';
|
|
5435
|
+
const schedule = plannedMessage.intervalMs
|
|
5436
|
+
? `repeats every ${formatTimeoutDurationHuman(plannedMessage.intervalMs)}`
|
|
5437
|
+
: `wakes you once at ${plannedMessage.dueAt}`;
|
|
5438
|
+
return `- \`${plannedMessage.timeoutId}\` ${schedule}: ${message}`;
|
|
5209
5439
|
}
|
|
5210
5440
|
|
|
5211
5441
|
// Note: [💞] This file defines the shared TEAM workspace convention rather than one standalone entity.
|
|
@@ -5236,8 +5466,8 @@
|
|
|
5236
5466
|
return '';
|
|
5237
5467
|
}
|
|
5238
5468
|
const teammateSections = workspace.manifest.teammates.map((teammate) => {
|
|
5239
|
-
const sourcePath = toPromptPath(path.join(workspace.relativeWorkspacePath, AGENT_TEAMMATE_SOURCES_DIRECTORY_NAME, teammate.sourceFileName));
|
|
5240
|
-
const transcriptPath = toPromptPath(path.join(workspace.relativeWorkspacePath, `${teammate.permanentId}--01.book`));
|
|
5469
|
+
const sourcePath = toPromptPath$1(path.join(workspace.relativeWorkspacePath, AGENT_TEAMMATE_SOURCES_DIRECTORY_NAME, teammate.sourceFileName));
|
|
5470
|
+
const transcriptPath = toPromptPath$1(path.join(workspace.relativeWorkspacePath, `${teammate.permanentId}--01.book`));
|
|
5241
5471
|
const instructions = teammate.instructions.trim() || 'No additional TEAM instructions were provided.';
|
|
5242
5472
|
return _spaceTrim.spaceTrim(`
|
|
5243
5473
|
- ${teammate.agentName}
|
|
@@ -5255,7 +5485,7 @@
|
|
|
5255
5485
|
|
|
5256
5486
|
- The underlying coding harness is already executing this turn **exactly once**. Never start, queue, or invoke another coding harness, agent runner, or \`ptbk\` command to consult a teammate.
|
|
5257
5487
|
- The primary agent remains responsible for the final user-facing \`MESSAGE @Agent\` answer.
|
|
5258
|
-
- Teammate source files are read-only context. When a teammate consultation occurs, record the actual exchange in a new top-level \`.book\` file in \`${toPromptPath(workspace.relativeWorkspacePath)}\`.
|
|
5488
|
+
- Teammate source files are read-only context. When a teammate consultation occurs, record the actual exchange in a new top-level \`.book\` file in \`${toPromptPath$1(workspace.relativeWorkspacePath)}\`.
|
|
5259
5489
|
- Name each transcript \`<teammate permanent id>--<sequence>.book\`, for example \`${workspace.manifest.teammates[0].permanentId}--01.book\`.
|
|
5260
5490
|
- Every transcript must contain alternating \`MESSAGE @${workspace.manifest.primaryAgent.agentName}\` and \`MESSAGE @<teammate name>\` blocks. Do not create a transcript for a teammate that was not consulted.
|
|
5261
5491
|
`);
|
|
@@ -5263,7 +5493,7 @@
|
|
|
5263
5493
|
/**
|
|
5264
5494
|
* Converts a filesystem-relative path into the portable path notation used in prompts.
|
|
5265
5495
|
*/
|
|
5266
|
-
function toPromptPath(path) {
|
|
5496
|
+
function toPromptPath$1(path) {
|
|
5267
5497
|
return path.replace(/\\/gu, '/');
|
|
5268
5498
|
}
|
|
5269
5499
|
|
|
@@ -5276,7 +5506,7 @@
|
|
|
5276
5506
|
|
|
5277
5507
|
- Read \`${messageRelativePath}\` and answer the most recent \`MESSAGE\` block. In a normal chat it is from \`@User\`; in your internal goal chat it can be from \`@Agent\`.
|
|
5278
5508
|
- Only change the queued message file by appending one new \`MESSAGE @Agent\` block
|
|
5279
|
-
${block(buildAllowedFileChangesPromptLine(options
|
|
5509
|
+
${block(buildAllowedFileChangesPromptLine(options))}
|
|
5280
5510
|
|
|
5281
5511
|
## Rules for the answering
|
|
5282
5512
|
|
|
@@ -5312,7 +5542,7 @@
|
|
|
5312
5542
|
|
|
5313
5543
|
- You can use \`message\` for message that will be sent immediately after clicking the button, or \`messageDraft\` for message that will be prefilled in the input field for editing before sending.
|
|
5314
5544
|
|
|
5315
|
-
${block(buildAgentGoalChatPromptSection(options.
|
|
5545
|
+
${block(buildAgentGoalChatPromptSection(options.plannedMessagesSidecar))}
|
|
5316
5546
|
|
|
5317
5547
|
${block(buildAgentProjectsPromptSection(options))}
|
|
5318
5548
|
|
|
@@ -5326,11 +5556,30 @@
|
|
|
5326
5556
|
/**
|
|
5327
5557
|
* Explains the exact files that one coding harness may change for a user turn.
|
|
5328
5558
|
*/
|
|
5329
|
-
function buildAllowedFileChangesPromptLine(
|
|
5330
|
-
|
|
5331
|
-
|
|
5559
|
+
function buildAllowedFileChangesPromptLine(options) {
|
|
5560
|
+
const allowedFileChanges = [`files inside your own \`${AGENT_PROJECTS_DIRECTORY_PATH}/\` directory`];
|
|
5561
|
+
if (options.teamWorkspace) {
|
|
5562
|
+
allowedFileChanges.push(`new consultation transcripts inside \`${toPromptPath(options.teamWorkspace.relativeWorkspacePath)}\``);
|
|
5563
|
+
}
|
|
5564
|
+
if (options.plannedMessagesSidecar) {
|
|
5565
|
+
allowedFileChanges.push(`the \`commands\` array of \`${toPromptPath(options.plannedMessagesSidecar.relativeSidecarPath)}\``);
|
|
5332
5566
|
}
|
|
5333
|
-
return `- Do not modify any other file in the repository, except
|
|
5567
|
+
return `- Do not modify any other file in the repository, except ${formatAllowedFileChanges(allowedFileChanges)}`;
|
|
5568
|
+
}
|
|
5569
|
+
/**
|
|
5570
|
+
* Joins the allowed file-change phrases into one readable enumeration.
|
|
5571
|
+
*/
|
|
5572
|
+
function formatAllowedFileChanges(allowedFileChanges) {
|
|
5573
|
+
if (allowedFileChanges.length === 1) {
|
|
5574
|
+
return allowedFileChanges[0];
|
|
5575
|
+
}
|
|
5576
|
+
return `${allowedFileChanges.slice(0, -1).join(', ')} and ${allowedFileChanges[allowedFileChanges.length - 1]}`;
|
|
5577
|
+
}
|
|
5578
|
+
/**
|
|
5579
|
+
* Converts a filesystem-relative path into the portable path notation used in prompts.
|
|
5580
|
+
*/
|
|
5581
|
+
function toPromptPath(path) {
|
|
5582
|
+
return path.replace(/\\/gu, '/');
|
|
5334
5583
|
}
|
|
5335
5584
|
|
|
5336
5585
|
/**
|
|
@@ -27345,6 +27594,30 @@
|
|
|
27345
27594
|
}
|
|
27346
27595
|
}
|
|
27347
27596
|
|
|
27597
|
+
/**
|
|
27598
|
+
* Pattern shared by Book parsing and editor highlighting for a commitment-like line.
|
|
27599
|
+
*
|
|
27600
|
+
* A Book commitment keyword consists of one or more all-uppercase words with at least
|
|
27601
|
+
* two characters each. This deliberately mirrors the Book editor syntax rule so an
|
|
27602
|
+
* unknown keyword starts a new source block everywhere it is interpreted.
|
|
27603
|
+
*
|
|
27604
|
+
* @private internal constant of `getBookCommitmentLineType`
|
|
27605
|
+
*/
|
|
27606
|
+
const BOOK_COMMITMENT_LINE_TYPE_REGEX = /^\s*(?<type>[A-Z][A-Z0-9]+(?:\s+[A-Z][A-Z0-9]+)*)(?=\s|$)/;
|
|
27607
|
+
/**
|
|
27608
|
+
* Extracts the uppercase commitment type from a Book line, including types not registered by Promptbook.
|
|
27609
|
+
*
|
|
27610
|
+
* @param line - One raw Book source line.
|
|
27611
|
+
* @returns Matched commitment type or `null` when the line does not begin with commitment syntax.
|
|
27612
|
+
*
|
|
27613
|
+
* @private internal utility of Book parsing and `<BookEditor/>`
|
|
27614
|
+
*/
|
|
27615
|
+
function getBookCommitmentLineType(line) {
|
|
27616
|
+
var _a;
|
|
27617
|
+
const match = BOOK_COMMITMENT_LINE_TYPE_REGEX.exec(line);
|
|
27618
|
+
return ((_a = match === null || match === void 0 ? void 0 : match.groups) === null || _a === void 0 ? void 0 : _a.type) || null;
|
|
27619
|
+
}
|
|
27620
|
+
|
|
27348
27621
|
/**
|
|
27349
27622
|
* Consumes the agent-name prelude from raw source.
|
|
27350
27623
|
*
|
|
@@ -27402,13 +27675,15 @@
|
|
|
27402
27675
|
return {
|
|
27403
27676
|
agentName: null,
|
|
27404
27677
|
commitments: [],
|
|
27678
|
+
unknownCommitments: [],
|
|
27405
27679
|
nonCommitmentLines: [],
|
|
27406
27680
|
};
|
|
27407
27681
|
}
|
|
27408
27682
|
const { lines, agentName, agentNameLineIndex, agentNameLineNumber } = parseAgentSourcePrelude(agentSource);
|
|
27409
27683
|
const commitments = [];
|
|
27684
|
+
const unknownCommitments = [];
|
|
27410
27685
|
const nonCommitmentLines = agentNameLineIndex >= 0 ? [lines[agentNameLineIndex]] : [];
|
|
27411
|
-
// Parse commitments with multiline support
|
|
27686
|
+
// Parse commitments with multiline support.
|
|
27412
27687
|
let currentCommitment = null;
|
|
27413
27688
|
// Process lines starting from after the agent name line
|
|
27414
27689
|
const startIndex = agentNameLineIndex >= 0 ? agentNameLineIndex + 1 : 0;
|
|
@@ -27422,25 +27697,11 @@
|
|
|
27422
27697
|
// Check if this line starts or ends a code block
|
|
27423
27698
|
if (trimmedLine.startsWith('```')) {
|
|
27424
27699
|
isInsideCodeBlock = !isInsideCodeBlock;
|
|
27425
|
-
|
|
27426
|
-
// If we are inside a commitment, the code block is part of it
|
|
27427
|
-
currentCommitment.contentLines.push(line);
|
|
27428
|
-
}
|
|
27429
|
-
else {
|
|
27430
|
-
// If we are not inside a commitment, the code block is non-commitment
|
|
27431
|
-
nonCommitmentLines.push(line);
|
|
27432
|
-
}
|
|
27700
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
27433
27701
|
continue;
|
|
27434
27702
|
}
|
|
27435
27703
|
if (isInsideCodeBlock) {
|
|
27436
|
-
|
|
27437
|
-
// If we are inside a commitment and a code block, the line is part of the commitment
|
|
27438
|
-
currentCommitment.contentLines.push(line);
|
|
27439
|
-
}
|
|
27440
|
-
else {
|
|
27441
|
-
// If we are inside a code block but not a commitment, the line is non-commitment
|
|
27442
|
-
nonCommitmentLines.push(line);
|
|
27443
|
-
}
|
|
27704
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
27444
27705
|
continue;
|
|
27445
27706
|
}
|
|
27446
27707
|
// Check if this line starts a new commitment
|
|
@@ -27449,22 +27710,14 @@
|
|
|
27449
27710
|
const typeRegex = definition.createTypeRegex();
|
|
27450
27711
|
const match = typeRegex.exec(line.trim());
|
|
27451
27712
|
if (match && ((_a = match.groups) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
27452
|
-
|
|
27453
|
-
if (currentCommitment) {
|
|
27454
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
27455
|
-
commitments.push({
|
|
27456
|
-
type: currentCommitment.type,
|
|
27457
|
-
content: _spaceTrim.spaceTrim(fullContent),
|
|
27458
|
-
originalLine: currentCommitment.originalStartLine,
|
|
27459
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
27460
|
-
});
|
|
27461
|
-
}
|
|
27713
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
27462
27714
|
// Extract the initial content from the commitment line
|
|
27463
27715
|
const fullRegex = definition.createRegex();
|
|
27464
27716
|
const fullMatch = fullRegex.exec(line.trim());
|
|
27465
27717
|
const initialContent = ((_b = fullMatch === null || fullMatch === void 0 ? void 0 : fullMatch.groups) === null || _b === void 0 ? void 0 : _b.contents) || '';
|
|
27466
27718
|
// Start a new commitment
|
|
27467
27719
|
currentCommitment = {
|
|
27720
|
+
kind: 'known',
|
|
27468
27721
|
type: definition.type,
|
|
27469
27722
|
startLineNumber: i + 1,
|
|
27470
27723
|
originalStartLine: line,
|
|
@@ -27474,52 +27727,90 @@
|
|
|
27474
27727
|
break;
|
|
27475
27728
|
}
|
|
27476
27729
|
}
|
|
27730
|
+
if (foundNewCommitment) {
|
|
27731
|
+
continue;
|
|
27732
|
+
}
|
|
27733
|
+
const unknownCommitmentType = getBookCommitmentLineType(line);
|
|
27734
|
+
if (unknownCommitmentType) {
|
|
27735
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
27736
|
+
currentCommitment = {
|
|
27737
|
+
kind: 'unknown',
|
|
27738
|
+
type: unknownCommitmentType,
|
|
27739
|
+
startLineNumber: i + 1,
|
|
27740
|
+
originalStartLine: line,
|
|
27741
|
+
sourceLines: [line],
|
|
27742
|
+
};
|
|
27743
|
+
continue;
|
|
27744
|
+
}
|
|
27477
27745
|
// Check if this is a horizontal line (ends any current commitment)
|
|
27478
27746
|
const isHorizontalLine = HORIZONTAL_LINE_PATTERN$1.test(line);
|
|
27479
27747
|
if (isHorizontalLine) {
|
|
27480
|
-
|
|
27481
|
-
|
|
27482
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
27483
|
-
commitments.push({
|
|
27484
|
-
type: currentCommitment.type,
|
|
27485
|
-
content: _spaceTrim.spaceTrim(fullContent),
|
|
27486
|
-
originalLine: currentCommitment.originalStartLine,
|
|
27487
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
27488
|
-
});
|
|
27489
|
-
currentCommitment = null;
|
|
27490
|
-
}
|
|
27748
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
27749
|
+
currentCommitment = null;
|
|
27491
27750
|
// Add horizontal line to non-commitment lines
|
|
27492
27751
|
nonCommitmentLines.push(line);
|
|
27493
27752
|
continue;
|
|
27494
27753
|
}
|
|
27495
|
-
|
|
27496
|
-
if (currentCommitment) {
|
|
27497
|
-
// This line belongs to the current commitment
|
|
27498
|
-
currentCommitment.contentLines.push(line);
|
|
27499
|
-
}
|
|
27500
|
-
else {
|
|
27501
|
-
// This line is not part of any commitment
|
|
27502
|
-
nonCommitmentLines.push(line);
|
|
27503
|
-
}
|
|
27504
|
-
}
|
|
27505
|
-
}
|
|
27506
|
-
// Don't forget to save the last commitment if it exists
|
|
27507
|
-
if (currentCommitment) {
|
|
27508
|
-
const fullContent = currentCommitment.contentLines.join('\n');
|
|
27509
|
-
commitments.push({
|
|
27510
|
-
type: currentCommitment.type,
|
|
27511
|
-
content: _spaceTrim.spaceTrim(fullContent),
|
|
27512
|
-
originalLine: currentCommitment.originalStartLine,
|
|
27513
|
-
lineNumber: currentCommitment.startLineNumber,
|
|
27514
|
-
});
|
|
27754
|
+
appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines);
|
|
27515
27755
|
}
|
|
27756
|
+
appendCurrentCommitment(currentCommitment, commitments, unknownCommitments);
|
|
27516
27757
|
return {
|
|
27517
27758
|
agentName,
|
|
27518
27759
|
agentNameLineNumber,
|
|
27519
27760
|
commitments,
|
|
27761
|
+
unknownCommitments,
|
|
27520
27762
|
nonCommitmentLines,
|
|
27521
27763
|
};
|
|
27522
27764
|
}
|
|
27765
|
+
/**
|
|
27766
|
+
* Stores the current known or unknown commitment in its appropriate parsed collection.
|
|
27767
|
+
*
|
|
27768
|
+
* @param currentCommitment - Commitment-like block collected so far.
|
|
27769
|
+
* @param commitments - Parsed registered commitments to append to.
|
|
27770
|
+
* @param unknownCommitments - Parsed unregistered commitments to append to.
|
|
27771
|
+
*
|
|
27772
|
+
* @private internal utility of `parseAgentSourceWithCommitments`
|
|
27773
|
+
*/
|
|
27774
|
+
function appendCurrentCommitment(currentCommitment, commitments, unknownCommitments) {
|
|
27775
|
+
if (!currentCommitment) {
|
|
27776
|
+
return;
|
|
27777
|
+
}
|
|
27778
|
+
if (currentCommitment.kind === 'unknown') {
|
|
27779
|
+
unknownCommitments.push({
|
|
27780
|
+
type: currentCommitment.type,
|
|
27781
|
+
originalLine: currentCommitment.originalStartLine,
|
|
27782
|
+
lineNumber: currentCommitment.startLineNumber,
|
|
27783
|
+
source: _spaceTrim.spaceTrim(currentCommitment.sourceLines.join('\n')),
|
|
27784
|
+
});
|
|
27785
|
+
return;
|
|
27786
|
+
}
|
|
27787
|
+
commitments.push({
|
|
27788
|
+
type: currentCommitment.type,
|
|
27789
|
+
content: _spaceTrim.spaceTrim(currentCommitment.contentLines.join('\n')),
|
|
27790
|
+
originalLine: currentCommitment.originalStartLine,
|
|
27791
|
+
lineNumber: currentCommitment.startLineNumber,
|
|
27792
|
+
});
|
|
27793
|
+
}
|
|
27794
|
+
/**
|
|
27795
|
+
* Adds one source line to the active commitment-like block, or to plain source content when none is active.
|
|
27796
|
+
*
|
|
27797
|
+
* @param currentCommitment - Commitment-like block currently being collected.
|
|
27798
|
+
* @param line - Source line to append.
|
|
27799
|
+
* @param nonCommitmentLines - Plain source lines to append to when no block is active.
|
|
27800
|
+
*
|
|
27801
|
+
* @private internal utility of `parseAgentSourceWithCommitments`
|
|
27802
|
+
*/
|
|
27803
|
+
function appendLineToCurrentCommitmentOrNonCommitmentLines(currentCommitment, line, nonCommitmentLines) {
|
|
27804
|
+
if (!currentCommitment) {
|
|
27805
|
+
nonCommitmentLines.push(line);
|
|
27806
|
+
return;
|
|
27807
|
+
}
|
|
27808
|
+
if (currentCommitment.kind === 'unknown') {
|
|
27809
|
+
currentCommitment.sourceLines.push(line);
|
|
27810
|
+
return;
|
|
27811
|
+
}
|
|
27812
|
+
currentCommitment.contentLines.push(line);
|
|
27813
|
+
}
|
|
27523
27814
|
|
|
27524
27815
|
/**
|
|
27525
27816
|
* Plugin for importing agent books *(`.book` files)*
|
|
@@ -27657,7 +27948,8 @@
|
|
|
27657
27948
|
requirements = await importReferencedFiles(requirements);
|
|
27658
27949
|
requirements = appendMcpServers(requirements, agentSource);
|
|
27659
27950
|
requirements = appendNonCommitmentContent(requirements, parseResult);
|
|
27660
|
-
|
|
27951
|
+
requirements = appendExampleInteractions(requirements, parseResult);
|
|
27952
|
+
return appendUnknownCommitmentContent(requirements, parseResult);
|
|
27661
27953
|
}
|
|
27662
27954
|
/**
|
|
27663
27955
|
* Imports text files referenced by IMPORT commitments and appends their transformed content to the system message.
|
|
@@ -27779,6 +28071,36 @@
|
|
|
27779
28071
|
}
|
|
27780
28072
|
return appendSystemMessageSection(requirements, nonCommitmentContent);
|
|
27781
28073
|
}
|
|
28074
|
+
/**
|
|
28075
|
+
* Appends unknown commitment blocks as final extra context without applying commitment side effects.
|
|
28076
|
+
*
|
|
28077
|
+
* @param requirements - Current requirements snapshot.
|
|
28078
|
+
* @param parseResult - Parsed source including unknown commitment blocks.
|
|
28079
|
+
* @returns Requirements with unknown commitment context appended at the end of the system message.
|
|
28080
|
+
*
|
|
28081
|
+
* @private internal utility of `augmentAgentModelRequirementsFromSource`
|
|
28082
|
+
*/
|
|
28083
|
+
function appendUnknownCommitmentContent(requirements, parseResult) {
|
|
28084
|
+
const unknownCommitmentContent = getUnknownCommitmentContent(parseResult);
|
|
28085
|
+
if (!unknownCommitmentContent) {
|
|
28086
|
+
return requirements;
|
|
28087
|
+
}
|
|
28088
|
+
return appendSystemMessageSection(requirements, unknownCommitmentContent);
|
|
28089
|
+
}
|
|
28090
|
+
/**
|
|
28091
|
+
* Joins unknown commitment blocks into their final extra-context representation.
|
|
28092
|
+
*
|
|
28093
|
+
* @param parseResult - Parsed source including unknown commitment blocks.
|
|
28094
|
+
* @returns Unknown commitment source blocks in their original order.
|
|
28095
|
+
*
|
|
28096
|
+
* @private internal utility of `appendUnknownCommitmentContent`
|
|
28097
|
+
*/
|
|
28098
|
+
function getUnknownCommitmentContent(parseResult) {
|
|
28099
|
+
return parseResult.unknownCommitments
|
|
28100
|
+
.map((commitment) => commitment.source)
|
|
28101
|
+
.filter(Boolean)
|
|
28102
|
+
.join('\n\n');
|
|
28103
|
+
}
|
|
27782
28104
|
/**
|
|
27783
28105
|
* Collects plain-text lines that were not parsed as commitments and should still become part of the final system message.
|
|
27784
28106
|
*
|
|
@@ -39753,23 +40075,27 @@
|
|
|
39753
40075
|
// TODO: [🧠][♿] Maybe export through `@promptbook/node`
|
|
39754
40076
|
|
|
39755
40077
|
/**
|
|
39756
|
-
* Attempts to locate the specified application on a Windows system by searching common installation directories.
|
|
40078
|
+
* Attempts to locate the specified application on a Windows system by searching PATH and common installation directories.
|
|
39757
40079
|
* Returns the path to the executable if found, or null otherwise.
|
|
39758
40080
|
*
|
|
39759
40081
|
* @private within the repository
|
|
39760
40082
|
*/
|
|
39761
40083
|
async function locateAppOnWindows({ appName, windowsSuffix, }) {
|
|
39762
40084
|
try {
|
|
39763
|
-
const
|
|
40085
|
+
const EXECUTABLE_FILENAME = windowsSuffix.replace(/^.*[\\/]/, '');
|
|
40086
|
+
const PATH_EXECUTABLE_PATHS = (process.env.PATH || '')
|
|
40087
|
+
.split(path.delimiter)
|
|
40088
|
+
.filter(Boolean)
|
|
40089
|
+
.map((pathPrefix) => path.join(pathPrefix, EXECUTABLE_FILENAME));
|
|
40090
|
+
const INSTALLATION_EXECUTABLE_PATHS = [
|
|
39764
40091
|
process.env.LOCALAPPDATA,
|
|
39765
40092
|
path.join(process.env.LOCALAPPDATA || '', 'Programs'),
|
|
39766
40093
|
process.env.PROGRAMFILES,
|
|
39767
40094
|
process.env['PROGRAMFILES(X86)'],
|
|
39768
|
-
];
|
|
39769
|
-
for (const
|
|
39770
|
-
|
|
39771
|
-
|
|
39772
|
-
return path;
|
|
40095
|
+
].map((pathPrefix) => pathPrefix + windowsSuffix);
|
|
40096
|
+
for (const executablePath of [...PATH_EXECUTABLE_PATHS, ...INSTALLATION_EXECUTABLE_PATHS]) {
|
|
40097
|
+
if (await isExecutable(executablePath, $provideFilesystemForNode())) {
|
|
40098
|
+
return executablePath;
|
|
39773
40099
|
}
|
|
39774
40100
|
}
|
|
39775
40101
|
throw new Error(`Can not locate app ${appName} on Windows.`);
|