@promptbook/cli 0.112.0-102 → 0.112.0-104
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/agents-server/README.md +0 -6
- package/apps/agents-server/src/app/AddAgentButton.tsx +0 -5
- package/apps/agents-server/src/app/actions.ts +50 -0
- package/apps/agents-server/src/app/admin/image-generator-test/ImageAttachmentsEditor.tsx +11 -6
- package/apps/agents-server/src/app/admin/metadata/MetadataClient.tsx +13 -15
- package/apps/agents-server/src/app/admin/servers/useCreateServerWizard.ts +13 -14
- package/apps/agents-server/src/app/agents/[agentName]/AgentProfileChat.tsx +3 -4
- package/apps/agents-server/src/app/api/health/route.ts +18 -0
- package/apps/agents-server/src/app/api/upload/route.ts +110 -383
- package/apps/agents-server/src/components/AgentProfile/AgentProfile.tsx +1 -4
- package/apps/agents-server/src/components/Header/Header.tsx +0 -11
- package/apps/agents-server/src/components/Header/useHeaderAgentMenus.tsx +0 -5
- package/apps/agents-server/src/components/NewAgentDialog/useNewAgentDialog.tsx +39 -16
- package/apps/agents-server/src/constants/defaultAgentAvatarVisual.ts +1 -1
- package/apps/agents-server/src/database/migrations/2026-06-0200-default-agent-avatar-visual-octopus3d3.sql +16 -0
- package/apps/agents-server/src/middleware.ts +2 -1
- package/apps/agents-server/src/tools/$provideCdnForServer.ts +87 -49
- package/apps/agents-server/src/utils/agentRouting/resolveAgentRouteTarget.ts +27 -4
- package/apps/agents-server/src/utils/cdn/classes/DigitalOceanSpaces.ts +17 -49
- package/apps/agents-server/src/utils/cdn/classes/TrackedFilesStorage.ts +5 -2
- package/apps/agents-server/src/utils/cdn/interfaces/IFilesStorage.ts +5 -0
- package/apps/agents-server/src/utils/defaultAgents/defaultAgents.ts +168 -0
- package/apps/agents-server/src/utils/defaultAgents/installDefaultAgents.ts +139 -0
- package/apps/agents-server/src/utils/shareTargetPayloads.ts +15 -63
- package/apps/agents-server/src/utils/upload/createBookEditorUploadHandler.ts +23 -150
- package/apps/agents-server/src/utils/upload/uploadFileToServer.ts +113 -0
- package/esm/index.es.js +711 -41
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/waitForPause.d.ts +12 -0
- package/esm/scripts/run-codex-prompts/main/runPromptRound.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +1 -0
- package/esm/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +1 -1
- package/esm/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/esm/src/avatars/visuals/octopus3d3AvatarVisual.d.ts +7 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/avatars/types/AvatarVisualDefinition.ts +1 -0
- package/src/avatars/visuals/avatarVisualRegistry.ts +2 -0
- package/src/avatars/visuals/octopus3d3AvatarVisual.ts +903 -0
- package/src/book-components/Chat/MarkdownContent/MarkdownContent.tsx +1 -3
- package/src/other/templates/getTemplatesPipelineCollection.ts +799 -809
- package/src/utils/agents/resolveAgentAvatarImageUrl.ts +1 -1
- package/src/version.ts +2 -2
- package/src/versions.txt +1 -0
- package/umd/index.umd.js +711 -41
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/waitForPause.d.ts +12 -0
- package/umd/scripts/run-codex-prompts/main/runPromptRound.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +1 -0
- package/umd/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +1 -1
- package/umd/src/avatars/types/AvatarVisualDefinition.d.ts +1 -1
- package/umd/src/avatars/visuals/octopus3d3AvatarVisual.d.ts +7 -0
- package/umd/src/version.d.ts +1 -1
- package/apps/agents-server/src/utils/cdn/resolveCdnStorageProvider.ts +0 -40
package/umd/index.umd.js
CHANGED
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
* @generated
|
|
61
61
|
* @see https://github.com/webgptorg/promptbook
|
|
62
62
|
*/
|
|
63
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
63
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-104';
|
|
64
64
|
/**
|
|
65
65
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
66
66
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -3617,16 +3617,30 @@
|
|
|
3617
3617
|
// Note: [🟡] Code for CLI runtime [buildAgentsServer](src/cli/cli-commands/agents-server/buildAgentsServer.ts) should never be published outside of `@promptbook/cli`
|
|
3618
3618
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
3619
3619
|
|
|
3620
|
+
/**
|
|
3621
|
+
* Default label used before the next pause checkpoint is known.
|
|
3622
|
+
*/
|
|
3623
|
+
const DEFAULT_PAUSE_TARGET_LABEL = 'the next task';
|
|
3620
3624
|
/**
|
|
3621
3625
|
* Current pause state.
|
|
3622
3626
|
*/
|
|
3623
3627
|
let pauseState = 'RUNNING';
|
|
3628
|
+
/**
|
|
3629
|
+
* Label of the next checkpoint where the requested pause will take effect.
|
|
3630
|
+
*/
|
|
3631
|
+
let pauseTargetLabel = DEFAULT_PAUSE_TARGET_LABEL;
|
|
3624
3632
|
/**
|
|
3625
3633
|
* Stores one new pause state in the shared runner controller.
|
|
3626
3634
|
*/
|
|
3627
3635
|
function setPauseState(nextPauseState) {
|
|
3628
3636
|
pauseState = nextPauseState;
|
|
3629
3637
|
}
|
|
3638
|
+
/**
|
|
3639
|
+
* Stores one new pause target label in the shared runner controller.
|
|
3640
|
+
*/
|
|
3641
|
+
function setPauseTargetLabel(nextPauseTargetLabel) {
|
|
3642
|
+
pauseTargetLabel = nextPauseTargetLabel.trim() || DEFAULT_PAUSE_TARGET_LABEL;
|
|
3643
|
+
}
|
|
3630
3644
|
/**
|
|
3631
3645
|
* Applies the same three-state toggle used by the `P` hotkey.
|
|
3632
3646
|
*/
|
|
@@ -3637,9 +3651,11 @@
|
|
|
3637
3651
|
}
|
|
3638
3652
|
if (pauseState === 'PAUSING') {
|
|
3639
3653
|
setPauseState('RUNNING');
|
|
3654
|
+
resetPauseTargetLabel();
|
|
3640
3655
|
return 'CANCELLED_PAUSE';
|
|
3641
3656
|
}
|
|
3642
3657
|
setPauseState('RUNNING');
|
|
3658
|
+
resetPauseTargetLabel();
|
|
3643
3659
|
return 'RESUMED';
|
|
3644
3660
|
}
|
|
3645
3661
|
/**
|
|
@@ -3680,7 +3696,8 @@
|
|
|
3680
3696
|
if (pauseState === 'PAUSING') {
|
|
3681
3697
|
setPauseState('PAUSED');
|
|
3682
3698
|
if (!(options === null || options === void 0 ? void 0 : options.silent)) {
|
|
3683
|
-
console.log(colors__default["default"].bgWhite.black(
|
|
3699
|
+
console.log(colors__default["default"].bgWhite.black(`Paused before ${getPauseTargetLabel()}`) +
|
|
3700
|
+
colors__default["default"].gray(' (Press "p" to resume)'));
|
|
3684
3701
|
}
|
|
3685
3702
|
(_a = options === null || options === void 0 ? void 0 : options.onPaused) === null || _a === void 0 ? void 0 : _a.call(options);
|
|
3686
3703
|
while (getPauseState() === 'PAUSED') {
|
|
@@ -3698,6 +3715,24 @@
|
|
|
3698
3715
|
function getPauseState() {
|
|
3699
3716
|
return pauseState;
|
|
3700
3717
|
}
|
|
3718
|
+
/**
|
|
3719
|
+
* Returns the label of the next checkpoint where pausing will take effect.
|
|
3720
|
+
*/
|
|
3721
|
+
function getPauseTargetLabel() {
|
|
3722
|
+
return pauseTargetLabel;
|
|
3723
|
+
}
|
|
3724
|
+
/**
|
|
3725
|
+
* Updates the label of the next pause checkpoint.
|
|
3726
|
+
*/
|
|
3727
|
+
function announcePauseTargetLabel(nextPauseTargetLabel) {
|
|
3728
|
+
setPauseTargetLabel(nextPauseTargetLabel);
|
|
3729
|
+
}
|
|
3730
|
+
/**
|
|
3731
|
+
* Restores the default generic pause target label.
|
|
3732
|
+
*/
|
|
3733
|
+
function resetPauseTargetLabel() {
|
|
3734
|
+
setPauseTargetLabel(DEFAULT_PAUSE_TARGET_LABEL);
|
|
3735
|
+
}
|
|
3701
3736
|
|
|
3702
3737
|
/**
|
|
3703
3738
|
* Just says that the variable is not used but should be kept
|
|
@@ -3935,18 +3970,18 @@
|
|
|
3935
3970
|
/**
|
|
3936
3971
|
* Builds the colored phase badge shown in the session box.
|
|
3937
3972
|
*/
|
|
3938
|
-
function buildPausePresentation(phase, pauseState, statusMessage) {
|
|
3973
|
+
function buildPausePresentation(phase, pauseState, pauseTargetLabel, statusMessage) {
|
|
3939
3974
|
if (pauseState === 'PAUSING') {
|
|
3940
3975
|
return {
|
|
3941
3976
|
badge: colors__default["default"].bgYellow.black(' PAUSING '),
|
|
3942
|
-
stateMessage:
|
|
3977
|
+
stateMessage: `Pausing before ${pauseTargetLabel}`,
|
|
3943
3978
|
pauseControl: colors__default["default"].bgMagenta.white(' P ') + colors__default["default"].white(' Cancel pause'),
|
|
3944
3979
|
};
|
|
3945
3980
|
}
|
|
3946
3981
|
if (pauseState === 'PAUSED') {
|
|
3947
3982
|
return {
|
|
3948
3983
|
badge: colors__default["default"].bgWhite.black(' PAUSED '),
|
|
3949
|
-
stateMessage:
|
|
3984
|
+
stateMessage: `Paused before ${pauseTargetLabel}`,
|
|
3950
3985
|
pauseControl: colors__default["default"].bgGreen.black(' P ') + colors__default["default"].white(' Resume'),
|
|
3951
3986
|
};
|
|
3952
3987
|
}
|
|
@@ -4078,7 +4113,7 @@
|
|
|
4078
4113
|
const octopusAnimationFrame = isCoderRunUiAutoRefreshing(options.phase, options.pauseState)
|
|
4079
4114
|
? options.animationFrame
|
|
4080
4115
|
: 0;
|
|
4081
|
-
const pausePresentation = buildPausePresentation(options.phase, options.pauseState, options.statusMessage);
|
|
4116
|
+
const pausePresentation = buildPausePresentation(options.phase, options.pauseState, options.pauseTargetLabel, options.statusMessage);
|
|
4082
4117
|
const sessionLines = buildSessionLines$1(options, totalWidth, pausePresentation);
|
|
4083
4118
|
const currentTaskLines = options.currentPromptLabel
|
|
4084
4119
|
? [
|
|
@@ -4706,6 +4741,7 @@
|
|
|
4706
4741
|
animationFrame: spinnerFrame,
|
|
4707
4742
|
spinner: SPINNER_FRAMES[spinnerFrame],
|
|
4708
4743
|
pauseState: getPauseState(),
|
|
4744
|
+
pauseTargetLabel: getPauseTargetLabel(),
|
|
4709
4745
|
config: state.config,
|
|
4710
4746
|
phase: state.phase,
|
|
4711
4747
|
currentPromptLabel: state.currentPromptLabel,
|
|
@@ -11007,7 +11043,7 @@
|
|
|
11007
11043
|
*
|
|
11008
11044
|
* @private helper of `minecraft2AvatarVisual`
|
|
11009
11045
|
*/
|
|
11010
|
-
const LIGHT_DIRECTION$
|
|
11046
|
+
const LIGHT_DIRECTION$3 = normalizeVector3({
|
|
11011
11047
|
x: 0.4,
|
|
11012
11048
|
y: -0.65,
|
|
11013
11049
|
z: 0.92,
|
|
@@ -11219,7 +11255,7 @@
|
|
|
11219
11255
|
corners: projectedCorners,
|
|
11220
11256
|
texture: faceDefinition.texture,
|
|
11221
11257
|
averageDepth: transformedCorners.reduce((depthSum, corner) => depthSum + corner.z, 0) / transformedCorners.length,
|
|
11222
|
-
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$
|
|
11258
|
+
lightIntensity: clampNumber$1(dotProduct3D(faceNormal, LIGHT_DIRECTION$3), -1, 1),
|
|
11223
11259
|
outlineColor: cuboid.outlineColor,
|
|
11224
11260
|
};
|
|
11225
11261
|
});
|
|
@@ -12410,7 +12446,7 @@
|
|
|
12410
12446
|
*
|
|
12411
12447
|
* @private helper of `octopus3dAvatarVisual`
|
|
12412
12448
|
*/
|
|
12413
|
-
const LIGHT_DIRECTION$
|
|
12449
|
+
const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
12414
12450
|
x: 0.48,
|
|
12415
12451
|
y: -0.62,
|
|
12416
12452
|
z: 0.94,
|
|
@@ -12620,7 +12656,7 @@
|
|
|
12620
12656
|
corners: projectedCorners,
|
|
12621
12657
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
12622
12658
|
transformedCorners.length,
|
|
12623
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$
|
|
12659
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$2), -1, 1),
|
|
12624
12660
|
fillStyle: resolveSurfacePatchFillStyle(palette, verticalProgress + verticalColorBias),
|
|
12625
12661
|
outlineColor,
|
|
12626
12662
|
});
|
|
@@ -12809,7 +12845,7 @@
|
|
|
12809
12845
|
*
|
|
12810
12846
|
* @private helper of `octopus3d2AvatarVisual`
|
|
12811
12847
|
*/
|
|
12812
|
-
const LIGHT_DIRECTION = normalizeVector3({
|
|
12848
|
+
const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
12813
12849
|
x: 0.38,
|
|
12814
12850
|
y: -0.6,
|
|
12815
12851
|
z: 0.98,
|
|
@@ -12958,7 +12994,7 @@
|
|
|
12958
12994
|
corners: projectedCorners,
|
|
12959
12995
|
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
12960
12996
|
transformedCorners.length,
|
|
12961
|
-
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
12997
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION$1), -1, 1),
|
|
12962
12998
|
fillStyle: resolveBlobbySurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), resolveLowerLobeWave(centerLongitude, morphologyProfile, animationPhase, timeMs)),
|
|
12963
12999
|
outlineColor: verticalProgress < 0.58 ? `${palette.highlight}73` : `${palette.shadow}8a`,
|
|
12964
13000
|
});
|
|
@@ -13058,6 +13094,516 @@
|
|
|
13058
13094
|
context.restore();
|
|
13059
13095
|
}
|
|
13060
13096
|
|
|
13097
|
+
/* eslint-disable no-magic-numbers */
|
|
13098
|
+
/**
|
|
13099
|
+
* Light direction used by the continuous octopus mesh shading.
|
|
13100
|
+
*
|
|
13101
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13102
|
+
*/
|
|
13103
|
+
const LIGHT_DIRECTION = normalizeVector3({
|
|
13104
|
+
x: 0.34,
|
|
13105
|
+
y: -0.62,
|
|
13106
|
+
z: 1,
|
|
13107
|
+
});
|
|
13108
|
+
/**
|
|
13109
|
+
* Real-octopus tentacle count used by the continuous lower mesh.
|
|
13110
|
+
*
|
|
13111
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13112
|
+
*/
|
|
13113
|
+
const OCTOPUS_TENTACLE_COUNT = 8;
|
|
13114
|
+
/**
|
|
13115
|
+
* Octopus 3D 3 avatar visual.
|
|
13116
|
+
*
|
|
13117
|
+
* @private built-in avatar visual
|
|
13118
|
+
*/
|
|
13119
|
+
const octopus3d3AvatarVisual = {
|
|
13120
|
+
id: 'octopus3d3',
|
|
13121
|
+
title: 'Octopus 3D 3',
|
|
13122
|
+
description: 'Cute continuous 3D octopus with a blobby single mesh, waving tentacle lobes, rich shading, and cursor-aware eyes.',
|
|
13123
|
+
isAnimated: true,
|
|
13124
|
+
supportsPointerTracking: true,
|
|
13125
|
+
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
13126
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
13127
|
+
const animationRandom = createRandom('octopus3d3-animation-profile');
|
|
13128
|
+
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
13129
|
+
const animationPhase = animationRandom() * Math.PI * 2;
|
|
13130
|
+
const tentacleProfiles = createContinuousTentacleProfiles(createRandom, morphologyProfile);
|
|
13131
|
+
const sceneCenterX = size * 0.5;
|
|
13132
|
+
const sceneCenterY = size * 0.535;
|
|
13133
|
+
const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
|
|
13134
|
+
const meshCenter = {
|
|
13135
|
+
x: interaction.bodyOffsetX * size * 0.048 + size * morphologyProfile.body.centerXJitterRatio * 0.44,
|
|
13136
|
+
y: -size * 0.07 + interaction.bodyOffsetY * size * 0.026 + bob,
|
|
13137
|
+
z: interaction.intensity * size * 0.018,
|
|
13138
|
+
};
|
|
13139
|
+
const rotationY = -0.1 +
|
|
13140
|
+
Math.sin(timeMs / 2700 + animationPhase) * 0.035 +
|
|
13141
|
+
interaction.bodyOffsetX * 0.22 +
|
|
13142
|
+
interaction.gazeX * 0.88;
|
|
13143
|
+
const rotationX = -0.07 +
|
|
13144
|
+
Math.cos(timeMs / 3100 + animationPhase * 0.7) * 0.018 -
|
|
13145
|
+
interaction.bodyOffsetY * 0.08 -
|
|
13146
|
+
interaction.gazeY * 0.38;
|
|
13147
|
+
const surfaceOptions = {
|
|
13148
|
+
radiusX: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.horizontalStretch * 1.1,
|
|
13149
|
+
radiusY: size * morphologyProfile.body.bodyRadiusRatio * morphologyProfile.body.verticalStretch * 1.08,
|
|
13150
|
+
radiusZ: size *
|
|
13151
|
+
morphologyProfile.body.bodyRadiusRatio *
|
|
13152
|
+
(1.02 + (morphologyProfile.body.horizontalStretch - 1) * 0.18),
|
|
13153
|
+
morphologyProfile,
|
|
13154
|
+
timeMs,
|
|
13155
|
+
animationPhase,
|
|
13156
|
+
tentacleProfiles,
|
|
13157
|
+
};
|
|
13158
|
+
const surfacePatches = resolveVisibleContinuousOctopusPatches({
|
|
13159
|
+
...surfaceOptions,
|
|
13160
|
+
center: meshCenter,
|
|
13161
|
+
rotationX,
|
|
13162
|
+
rotationY,
|
|
13163
|
+
sceneCenterX,
|
|
13164
|
+
sceneCenterY,
|
|
13165
|
+
size,
|
|
13166
|
+
palette,
|
|
13167
|
+
});
|
|
13168
|
+
const eyeLatitude = clampNumber$1(morphologyProfile.face.eyeCenterYOffsetRatio * 4.2 - 0.03, -0.22, 0.08);
|
|
13169
|
+
const eyeLongitude = clampNumber$1(morphologyProfile.face.eyeSpacingRatio * 3.1, 0.18, 0.32);
|
|
13170
|
+
const mouthLatitude = clampNumber$1(eyeLatitude + 0.2 + morphologyProfile.face.mouthYOffsetRatio, 0.08, 0.34);
|
|
13171
|
+
const mouthCenterLongitude = clampNumber$1(morphologyProfile.face.mouthCenterOffsetRatio * 5.6, -0.08, 0.08);
|
|
13172
|
+
const mouthHalfLongitude = clampNumber$1(eyeLongitude * 0.78, 0.15, 0.28);
|
|
13173
|
+
const mouthCurveLatitude = clampNumber$1(mouthLatitude + morphologyProfile.face.mouthCurveDepthRatio * 0.78, mouthLatitude + 0.03, 0.42);
|
|
13174
|
+
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.76;
|
|
13175
|
+
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.9;
|
|
13176
|
+
drawAvatarFrame(context, size, palette);
|
|
13177
|
+
drawContinuousOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs);
|
|
13178
|
+
drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile);
|
|
13179
|
+
for (const surfacePatch of surfacePatches.sort((firstSurfacePatch, secondSurfacePatch) => firstSurfacePatch.averageDepth - secondSurfacePatch.averageDepth)) {
|
|
13180
|
+
drawContinuousSurfacePatch(context, surfacePatch);
|
|
13181
|
+
}
|
|
13182
|
+
drawProjectedSurfaceCurrents({
|
|
13183
|
+
context,
|
|
13184
|
+
surfaceOptions,
|
|
13185
|
+
center: meshCenter,
|
|
13186
|
+
rotationX,
|
|
13187
|
+
rotationY,
|
|
13188
|
+
sceneCenterX,
|
|
13189
|
+
sceneCenterY,
|
|
13190
|
+
size,
|
|
13191
|
+
palette,
|
|
13192
|
+
morphologyProfile,
|
|
13193
|
+
timeMs,
|
|
13194
|
+
animationPhase,
|
|
13195
|
+
});
|
|
13196
|
+
drawProjectedTentacleSuckers({
|
|
13197
|
+
context,
|
|
13198
|
+
surfaceOptions,
|
|
13199
|
+
center: meshCenter,
|
|
13200
|
+
rotationX,
|
|
13201
|
+
rotationY,
|
|
13202
|
+
sceneCenterX,
|
|
13203
|
+
sceneCenterY,
|
|
13204
|
+
size,
|
|
13205
|
+
palette,
|
|
13206
|
+
});
|
|
13207
|
+
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
13208
|
+
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 + eyeRandom() * 0.7, interaction, morphologyProfile.face.eyeStyle);
|
|
13209
|
+
drawProjectedOrganicMouth(context, [
|
|
13210
|
+
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
13211
|
+
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
13212
|
+
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude + mouthHalfLongitude),
|
|
13213
|
+
], meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, palette, size);
|
|
13214
|
+
},
|
|
13215
|
+
};
|
|
13216
|
+
/**
|
|
13217
|
+
* Creates seeded tentacle-lobe profiles around the visible lower octopus body.
|
|
13218
|
+
*
|
|
13219
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13220
|
+
*/
|
|
13221
|
+
function createContinuousTentacleProfiles(createRandom, morphologyProfile) {
|
|
13222
|
+
return Array.from({ length: OCTOPUS_TENTACLE_COUNT }, (_, tentacleIndex) => {
|
|
13223
|
+
const tentacleRandom = createRandom(`octopus3d3-tentacle-${tentacleIndex}`);
|
|
13224
|
+
const progress = tentacleIndex / (OCTOPUS_TENTACLE_COUNT - 1);
|
|
13225
|
+
return {
|
|
13226
|
+
centerLongitude: -Math.PI * 0.86 +
|
|
13227
|
+
progress * Math.PI * 1.72 +
|
|
13228
|
+
(tentacleRandom() - 0.5) * (0.08 + morphologyProfile.tentacles.rootSpreadScale * 0.03),
|
|
13229
|
+
widthScale: 0.86 + tentacleRandom() * 0.34 + (morphologyProfile.tentacles.baseWidthScale - 1) * 0.16,
|
|
13230
|
+
lengthScale: 0.86 + tentacleRandom() * 0.36 + (morphologyProfile.tentacles.flowLengthScale - 1) * 0.22,
|
|
13231
|
+
swayScale: 0.82 + tentacleRandom() * 0.38 + (morphologyProfile.tentacles.swayScale - 1) * 0.2,
|
|
13232
|
+
depthScale: 0.86 + tentacleRandom() * 0.32 + (morphologyProfile.tentacles.tipReachScale - 1) * 0.2,
|
|
13233
|
+
phase: tentacleRandom() * Math.PI * 2,
|
|
13234
|
+
suckerSide: tentacleRandom() > 0.5 ? 1 : -1,
|
|
13235
|
+
};
|
|
13236
|
+
});
|
|
13237
|
+
}
|
|
13238
|
+
/**
|
|
13239
|
+
* Draws the soft underwater atmosphere behind the continuous octopus mesh.
|
|
13240
|
+
*
|
|
13241
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13242
|
+
*/
|
|
13243
|
+
function drawContinuousOctopusAtmosphere(context, size, palette, sceneCenterX, sceneCenterY, interaction, timeMs) {
|
|
13244
|
+
const glowGradient = context.createRadialGradient(sceneCenterX + interaction.gazeX * size * 0.11, sceneCenterY - size * 0.17 + interaction.gazeY * size * 0.05, size * 0.04, sceneCenterX, sceneCenterY, size * (0.66 + interaction.intensity * 0.02));
|
|
13245
|
+
glowGradient.addColorStop(0, `${palette.highlight}66`);
|
|
13246
|
+
glowGradient.addColorStop(0.34, `${palette.accent}2e`);
|
|
13247
|
+
glowGradient.addColorStop(1, `${palette.highlight}00`);
|
|
13248
|
+
context.fillStyle = glowGradient;
|
|
13249
|
+
context.fillRect(0, 0, size, size);
|
|
13250
|
+
const lowerGradient = context.createRadialGradient(sceneCenterX + Math.sin(timeMs / 1550) * size * 0.05, sceneCenterY + size * 0.29, size * 0.06, sceneCenterX, sceneCenterY + size * 0.3, size * 0.54);
|
|
13251
|
+
lowerGradient.addColorStop(0, `${palette.secondary}25`);
|
|
13252
|
+
lowerGradient.addColorStop(1, `${palette.secondary}00`);
|
|
13253
|
+
context.fillStyle = lowerGradient;
|
|
13254
|
+
context.fillRect(0, 0, size, size);
|
|
13255
|
+
}
|
|
13256
|
+
/**
|
|
13257
|
+
* Draws the soft lower shadow that anchors the octopus in the avatar frame.
|
|
13258
|
+
*
|
|
13259
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13260
|
+
*/
|
|
13261
|
+
function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
13262
|
+
context.save();
|
|
13263
|
+
context.fillStyle = `${palette.shadow}66`;
|
|
13264
|
+
context.filter = `blur(${size * 0.025}px)`;
|
|
13265
|
+
context.beginPath();
|
|
13266
|
+
context.ellipse(size * 0.5 + interaction.gazeX * size * 0.045, size * 0.9 + Math.sin(timeMs / 980) * size * 0.007, size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02), size * 0.06, 0, 0, Math.PI * 2);
|
|
13267
|
+
context.fill();
|
|
13268
|
+
context.restore();
|
|
13269
|
+
}
|
|
13270
|
+
/**
|
|
13271
|
+
* Resolves visible projected patches for the continuous octopus mesh.
|
|
13272
|
+
*
|
|
13273
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13274
|
+
*/
|
|
13275
|
+
function resolveVisibleContinuousOctopusPatches(options) {
|
|
13276
|
+
const { center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette } = options;
|
|
13277
|
+
const latitudePatchCount = 16;
|
|
13278
|
+
const longitudePatchCount = 40;
|
|
13279
|
+
const surfacePatches = [];
|
|
13280
|
+
for (let latitudeIndex = 0; latitudeIndex < latitudePatchCount; latitudeIndex++) {
|
|
13281
|
+
const startLatitude = -Math.PI / 2 + (latitudeIndex / latitudePatchCount) * Math.PI;
|
|
13282
|
+
const endLatitude = -Math.PI / 2 + ((latitudeIndex + 1) / latitudePatchCount) * Math.PI;
|
|
13283
|
+
const centerLatitude = (startLatitude + endLatitude) / 2;
|
|
13284
|
+
const verticalProgress = (Math.sin(centerLatitude) + 1) / 2;
|
|
13285
|
+
for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
|
|
13286
|
+
const startLongitude = -Math.PI + (longitudeIndex / longitudePatchCount) * Math.PI * 2;
|
|
13287
|
+
const endLongitude = -Math.PI + ((longitudeIndex + 1) / longitudePatchCount) * Math.PI * 2;
|
|
13288
|
+
const centerLongitude = (startLongitude + endLongitude) / 2;
|
|
13289
|
+
const localCorners = [
|
|
13290
|
+
sampleContinuousOctopusSurfacePoint(options, startLatitude, startLongitude),
|
|
13291
|
+
sampleContinuousOctopusSurfacePoint(options, startLatitude, endLongitude),
|
|
13292
|
+
sampleContinuousOctopusSurfacePoint(options, endLatitude, endLongitude),
|
|
13293
|
+
sampleContinuousOctopusSurfacePoint(options, endLatitude, startLongitude),
|
|
13294
|
+
];
|
|
13295
|
+
const transformedCorners = localCorners.map((localCorner) => transformScenePoint(localCorner, center, rotationX, rotationY));
|
|
13296
|
+
const surfaceNormal = normalizeVector3(crossProduct3D(subtractPoint3D(transformedCorners[1], transformedCorners[0]), subtractPoint3D(transformedCorners[2], transformedCorners[0])));
|
|
13297
|
+
if (surfaceNormal.z <= 0.008) {
|
|
13298
|
+
continue;
|
|
13299
|
+
}
|
|
13300
|
+
const projectedCorners = transformedCorners.map((transformedCorner) => projectScenePoint(transformedCorner, size, sceneCenterX, sceneCenterY));
|
|
13301
|
+
const tentacleInfluence = resolveContinuousTentacleInfluence(options, centerLongitude);
|
|
13302
|
+
const lowerLobeWave = resolveContinuousLobeWave(options, centerLongitude);
|
|
13303
|
+
surfacePatches.push({
|
|
13304
|
+
corners: projectedCorners,
|
|
13305
|
+
averageDepth: transformedCorners.reduce((depthSum, transformedCorner) => depthSum + transformedCorner.z, 0) /
|
|
13306
|
+
transformedCorners.length,
|
|
13307
|
+
lightIntensity: clampNumber$1(dotProduct3D(surfaceNormal, LIGHT_DIRECTION), -1, 1),
|
|
13308
|
+
fillStyle: resolveContinuousSurfacePatchFillStyle(palette, verticalProgress, Math.max(0, Math.cos(centerLongitude)), tentacleInfluence.core, lowerLobeWave),
|
|
13309
|
+
outlineColor: verticalProgress < 0.54 ? `${palette.highlight}69` : `${palette.shadow}78`,
|
|
13310
|
+
});
|
|
13311
|
+
}
|
|
13312
|
+
}
|
|
13313
|
+
return surfacePatches;
|
|
13314
|
+
}
|
|
13315
|
+
/**
|
|
13316
|
+
* Samples one point on the continuous Octopus 3D 3 surface.
|
|
13317
|
+
*
|
|
13318
|
+
* The lower hemisphere is pulled into eight seeded waving lobes, so the portrait reads as
|
|
13319
|
+
* tentacled while still being rendered as one connected blobby mesh.
|
|
13320
|
+
*
|
|
13321
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13322
|
+
*/
|
|
13323
|
+
function sampleContinuousOctopusSurfacePoint(options, latitude, longitude) {
|
|
13324
|
+
const { radiusX, radiusY, radiusZ, morphologyProfile, timeMs, animationPhase } = options;
|
|
13325
|
+
const cosineLatitude = Math.max(0, Math.cos(latitude));
|
|
13326
|
+
const verticalProgress = (Math.sin(latitude) + 1) / 2;
|
|
13327
|
+
const upperBlend = Math.pow(1 - verticalProgress, 1.28);
|
|
13328
|
+
const lowerBlend = smoothStep(0.38, 1, verticalProgress);
|
|
13329
|
+
const tipBlend = smoothStep(0.68, 1, verticalProgress);
|
|
13330
|
+
const tentacleInfluence = resolveContinuousTentacleInfluence(options, longitude);
|
|
13331
|
+
const centerPull = resolveSignedAngularDistance(longitude, tentacleInfluence.centerLongitude);
|
|
13332
|
+
const effectiveLongitude = longitude + centerPull * lowerBlend * tentacleInfluence.core * (0.24 + tipBlend * 0.2);
|
|
13333
|
+
const lowerLobeWave = resolveContinuousLobeWave(options, longitude);
|
|
13334
|
+
const mantleRipple = Math.sin(longitude * morphologyProfile.body.lobeCount +
|
|
13335
|
+
animationPhase * 0.6 +
|
|
13336
|
+
timeMs / (1750 + morphologyProfile.body.lobeCount * 30)) *
|
|
13337
|
+
(0.018 + morphologyProfile.body.wobbleAmplitudeRatio * 0.8) *
|
|
13338
|
+
(0.3 + lowerBlend * 0.7);
|
|
13339
|
+
const tentacleWave = Math.sin(timeMs / 760 + tentacleInfluence.phase + verticalProgress * 2.4) *
|
|
13340
|
+
lowerBlend *
|
|
13341
|
+
tentacleInfluence.core *
|
|
13342
|
+
tentacleInfluence.swayScale;
|
|
13343
|
+
const horizontalScale = 1.04 +
|
|
13344
|
+
mantleRipple +
|
|
13345
|
+
lowerBlend * (0.16 + (morphologyProfile.tentacles.rootSpreadScale - 1) * 0.1) +
|
|
13346
|
+
lowerBlend * tentacleInfluence.core * (0.2 + lowerLobeWave * 0.12) -
|
|
13347
|
+
upperBlend * 0.08;
|
|
13348
|
+
const depthScale = 1.06 +
|
|
13349
|
+
upperBlend * 0.16 +
|
|
13350
|
+
Math.max(0, Math.cos(effectiveLongitude)) * 0.1 +
|
|
13351
|
+
lowerBlend * tentacleInfluence.core * (0.1 + tentacleInfluence.depthScale * 0.06) -
|
|
13352
|
+
Math.max(0, -Math.cos(effectiveLongitude)) * 0.05;
|
|
13353
|
+
const tentacleTubeRadius = lowerBlend *
|
|
13354
|
+
tentacleInfluence.core *
|
|
13355
|
+
(0.11 + tipBlend * 0.06 + tentacleInfluence.widthScale * 0.025) *
|
|
13356
|
+
radiusX;
|
|
13357
|
+
const planarRadiusX = cosineLatitude * radiusX * horizontalScale + tentacleTubeRadius;
|
|
13358
|
+
const planarRadiusZ = cosineLatitude * radiusZ * depthScale + tentacleTubeRadius * 0.72;
|
|
13359
|
+
const lowerDrop = lowerBlend *
|
|
13360
|
+
radiusY *
|
|
13361
|
+
(0.18 +
|
|
13362
|
+
tentacleInfluence.core *
|
|
13363
|
+
(0.38 +
|
|
13364
|
+
tentacleInfluence.lengthScale * 0.22 +
|
|
13365
|
+
(morphologyProfile.tentacles.flowLengthScale - 1) * 0.08));
|
|
13366
|
+
return {
|
|
13367
|
+
x: Math.sin(effectiveLongitude) * planarRadiusX +
|
|
13368
|
+
tentacleWave * radiusX * (0.052 + tipBlend * 0.05),
|
|
13369
|
+
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.12) -
|
|
13370
|
+
upperBlend * radiusY * 0.1 +
|
|
13371
|
+
lowerDrop +
|
|
13372
|
+
Math.sin(timeMs / 1420 + animationPhase + latitude * 1.6) * lowerBlend * radiusY * 0.018 +
|
|
13373
|
+
Math.cos(timeMs / 880 + tentacleInfluence.phase) *
|
|
13374
|
+
lowerBlend *
|
|
13375
|
+
tipBlend *
|
|
13376
|
+
tentacleInfluence.core *
|
|
13377
|
+
radiusY *
|
|
13378
|
+
0.034,
|
|
13379
|
+
z: Math.cos(effectiveLongitude) * planarRadiusZ +
|
|
13380
|
+
Math.cos(timeMs / 980 + tentacleInfluence.phase + verticalProgress) *
|
|
13381
|
+
lowerBlend *
|
|
13382
|
+
tentacleInfluence.core *
|
|
13383
|
+
radiusZ *
|
|
13384
|
+
0.04,
|
|
13385
|
+
};
|
|
13386
|
+
}
|
|
13387
|
+
/**
|
|
13388
|
+
* Blends nearby seeded tentacle profiles at one mesh longitude.
|
|
13389
|
+
*
|
|
13390
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13391
|
+
*/
|
|
13392
|
+
function resolveContinuousTentacleInfluence(options, longitude) {
|
|
13393
|
+
let totalWeight = 0;
|
|
13394
|
+
let weightedSin = 0;
|
|
13395
|
+
let weightedCos = 0;
|
|
13396
|
+
let weightedWidthScale = 0;
|
|
13397
|
+
let weightedLengthScale = 0;
|
|
13398
|
+
let weightedSwayScale = 0;
|
|
13399
|
+
let weightedDepthScale = 0;
|
|
13400
|
+
let weightedPhase = 0;
|
|
13401
|
+
for (const tentacleProfile of options.tentacleProfiles) {
|
|
13402
|
+
const distance = Math.abs(resolveSignedAngularDistance(longitude, tentacleProfile.centerLongitude));
|
|
13403
|
+
const width = 0.2 * tentacleProfile.widthScale;
|
|
13404
|
+
const weight = Math.exp(-(distance * distance) / (width * width));
|
|
13405
|
+
totalWeight += weight;
|
|
13406
|
+
weightedSin += Math.sin(tentacleProfile.centerLongitude) * weight;
|
|
13407
|
+
weightedCos += Math.cos(tentacleProfile.centerLongitude) * weight;
|
|
13408
|
+
weightedWidthScale += tentacleProfile.widthScale * weight;
|
|
13409
|
+
weightedLengthScale += tentacleProfile.lengthScale * weight;
|
|
13410
|
+
weightedSwayScale += tentacleProfile.swayScale * weight;
|
|
13411
|
+
weightedDepthScale += tentacleProfile.depthScale * weight;
|
|
13412
|
+
weightedPhase += tentacleProfile.phase * weight;
|
|
13413
|
+
}
|
|
13414
|
+
if (totalWeight < 0.0001) {
|
|
13415
|
+
return {
|
|
13416
|
+
core: 0,
|
|
13417
|
+
centerLongitude: longitude,
|
|
13418
|
+
widthScale: 1,
|
|
13419
|
+
lengthScale: 1,
|
|
13420
|
+
swayScale: 1,
|
|
13421
|
+
depthScale: 1,
|
|
13422
|
+
phase: 0,
|
|
13423
|
+
};
|
|
13424
|
+
}
|
|
13425
|
+
return {
|
|
13426
|
+
core: clampNumber$1(totalWeight, 0, 1),
|
|
13427
|
+
centerLongitude: Math.atan2(weightedSin / totalWeight, weightedCos / totalWeight),
|
|
13428
|
+
widthScale: weightedWidthScale / totalWeight,
|
|
13429
|
+
lengthScale: weightedLengthScale / totalWeight,
|
|
13430
|
+
swayScale: weightedSwayScale / totalWeight,
|
|
13431
|
+
depthScale: weightedDepthScale / totalWeight,
|
|
13432
|
+
phase: weightedPhase / totalWeight,
|
|
13433
|
+
};
|
|
13434
|
+
}
|
|
13435
|
+
/**
|
|
13436
|
+
* Resolves the soft lower wave that makes the continuous mesh read as a set of tentacles.
|
|
13437
|
+
*
|
|
13438
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13439
|
+
*/
|
|
13440
|
+
function resolveContinuousLobeWave(options, longitude) {
|
|
13441
|
+
const { morphologyProfile, animationPhase, timeMs } = options;
|
|
13442
|
+
return (Math.cos(longitude * OCTOPUS_TENTACLE_COUNT + animationPhase + timeMs / (980 + morphologyProfile.body.lobeCount * 18)) +
|
|
13443
|
+
1) / 2;
|
|
13444
|
+
}
|
|
13445
|
+
/**
|
|
13446
|
+
* Resolves one base fill tone for a patch on the continuous octopus mesh.
|
|
13447
|
+
*
|
|
13448
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13449
|
+
*/
|
|
13450
|
+
function resolveContinuousSurfacePatchFillStyle(palette, verticalProgress, forwardness, tentacleCore, lowerLobeWave) {
|
|
13451
|
+
const tonalProgress = clampNumber$1(verticalProgress + lowerLobeWave * 0.1 + tentacleCore * 0.08 - forwardness * 0.08, 0, 1);
|
|
13452
|
+
if (tonalProgress < 0.14) {
|
|
13453
|
+
return palette.highlight;
|
|
13454
|
+
}
|
|
13455
|
+
if (tonalProgress < 0.32) {
|
|
13456
|
+
return palette.secondary;
|
|
13457
|
+
}
|
|
13458
|
+
if (tonalProgress < 0.72) {
|
|
13459
|
+
return forwardness > 0.55 ? palette.secondary : palette.primary;
|
|
13460
|
+
}
|
|
13461
|
+
return tentacleCore > 0.44 ? `${palette.primary}f4` : `${palette.shadow}ee`;
|
|
13462
|
+
}
|
|
13463
|
+
/**
|
|
13464
|
+
* Draws one projected mesh patch with soft shading and a subtle edge.
|
|
13465
|
+
*
|
|
13466
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13467
|
+
*/
|
|
13468
|
+
function drawContinuousSurfacePatch(context, surfacePatch) {
|
|
13469
|
+
drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
|
|
13470
|
+
if (surfacePatch.lightIntensity > 0) {
|
|
13471
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.18 * surfacePatch.lightIntensity})`);
|
|
13472
|
+
}
|
|
13473
|
+
else if (surfacePatch.lightIntensity < 0) {
|
|
13474
|
+
drawProjectedQuad(context, surfacePatch.corners, `rgba(0, 0, 0, ${0.25 * Math.abs(surfacePatch.lightIntensity)})`);
|
|
13475
|
+
}
|
|
13476
|
+
context.save();
|
|
13477
|
+
context.beginPath();
|
|
13478
|
+
context.moveTo(surfacePatch.corners[0].x, surfacePatch.corners[0].y);
|
|
13479
|
+
for (let cornerIndex = 1; cornerIndex < surfacePatch.corners.length; cornerIndex++) {
|
|
13480
|
+
context.lineTo(surfacePatch.corners[cornerIndex].x, surfacePatch.corners[cornerIndex].y);
|
|
13481
|
+
}
|
|
13482
|
+
context.closePath();
|
|
13483
|
+
context.strokeStyle = surfacePatch.outlineColor;
|
|
13484
|
+
context.lineWidth = Math.max(0.7, getProjectedQuadPerimeter(surfacePatch.corners) * 0.0032);
|
|
13485
|
+
context.lineJoin = 'round';
|
|
13486
|
+
context.stroke();
|
|
13487
|
+
context.restore();
|
|
13488
|
+
}
|
|
13489
|
+
/**
|
|
13490
|
+
* Draws projected mantle-current lines on the front of the mesh.
|
|
13491
|
+
*
|
|
13492
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13493
|
+
*/
|
|
13494
|
+
function drawProjectedSurfaceCurrents(options) {
|
|
13495
|
+
const { context, surfaceOptions, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, morphologyProfile, timeMs, animationPhase, } = options;
|
|
13496
|
+
const currentCount = Math.min(6, morphologyProfile.details.mantleCurrentCount);
|
|
13497
|
+
const centerIndex = (currentCount - 1) / 2;
|
|
13498
|
+
context.save();
|
|
13499
|
+
context.lineCap = 'round';
|
|
13500
|
+
context.lineJoin = 'round';
|
|
13501
|
+
for (let currentIndex = 0; currentIndex < currentCount; currentIndex++) {
|
|
13502
|
+
const baseLongitude = (currentIndex - centerIndex) * 0.15;
|
|
13503
|
+
const projectedPoints = [];
|
|
13504
|
+
for (let sampleIndex = 0; sampleIndex < 8; sampleIndex++) {
|
|
13505
|
+
const progress = sampleIndex / 7;
|
|
13506
|
+
const latitude = -0.46 + progress * 0.74;
|
|
13507
|
+
const longitude = baseLongitude +
|
|
13508
|
+
Math.sin(timeMs / 1160 + animationPhase + currentIndex * 0.7 + progress * 2) * 0.035;
|
|
13509
|
+
const scenePoint = transformScenePoint(sampleContinuousOctopusSurfacePoint(surfaceOptions, latitude, longitude), center, rotationX, rotationY);
|
|
13510
|
+
if (scenePoint.z > center.z - size * 0.016) {
|
|
13511
|
+
projectedPoints.push(projectScenePoint(scenePoint, size, sceneCenterX, sceneCenterY));
|
|
13512
|
+
}
|
|
13513
|
+
}
|
|
13514
|
+
if (projectedPoints.length < 3) {
|
|
13515
|
+
continue;
|
|
13516
|
+
}
|
|
13517
|
+
context.beginPath();
|
|
13518
|
+
context.moveTo(projectedPoints[0].x, projectedPoints[0].y);
|
|
13519
|
+
for (const projectedPoint of projectedPoints.slice(1)) {
|
|
13520
|
+
context.lineTo(projectedPoint.x, projectedPoint.y);
|
|
13521
|
+
}
|
|
13522
|
+
context.strokeStyle = currentIndex % 2 === 0 ? `${palette.highlight}3d` : `${palette.accent}33`;
|
|
13523
|
+
context.lineWidth = size * (0.0055 + currentIndex * 0.00045);
|
|
13524
|
+
context.stroke();
|
|
13525
|
+
}
|
|
13526
|
+
context.restore();
|
|
13527
|
+
}
|
|
13528
|
+
/**
|
|
13529
|
+
* Draws small projected sucker highlights on the waving lower mesh lobes.
|
|
13530
|
+
*
|
|
13531
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13532
|
+
*/
|
|
13533
|
+
function drawProjectedTentacleSuckers(options) {
|
|
13534
|
+
const { surfaceOptions, size } = options;
|
|
13535
|
+
const { timeMs } = surfaceOptions;
|
|
13536
|
+
for (const tentacleProfile of surfaceOptions.tentacleProfiles) {
|
|
13537
|
+
if (Math.cos(tentacleProfile.centerLongitude) < -0.12) {
|
|
13538
|
+
continue;
|
|
13539
|
+
}
|
|
13540
|
+
for (let suckerIndex = 0; suckerIndex < 3; suckerIndex++) {
|
|
13541
|
+
const latitude = 0.52 + suckerIndex * 0.14;
|
|
13542
|
+
const sideOffset = tentacleProfile.suckerSide * (0.035 + suckerIndex * 0.012) * tentacleProfile.widthScale;
|
|
13543
|
+
const waveOffset = Math.sin(timeMs / 900 + tentacleProfile.phase + suckerIndex * 0.8) * 0.018;
|
|
13544
|
+
drawProjectedSurfaceSpot({
|
|
13545
|
+
...options,
|
|
13546
|
+
latitude,
|
|
13547
|
+
longitude: tentacleProfile.centerLongitude + sideOffset + waveOffset,
|
|
13548
|
+
radiusScale: size * (0.0065 - suckerIndex * 0.0007),
|
|
13549
|
+
});
|
|
13550
|
+
}
|
|
13551
|
+
}
|
|
13552
|
+
}
|
|
13553
|
+
/**
|
|
13554
|
+
* Draws one tiny projected surface spot by sampling local mesh tangents.
|
|
13555
|
+
*
|
|
13556
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13557
|
+
*/
|
|
13558
|
+
function drawProjectedSurfaceSpot(options) {
|
|
13559
|
+
const { context, surfaceOptions, center, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, latitude, longitude, radiusScale, } = options;
|
|
13560
|
+
const localCenter = sampleContinuousOctopusSurfacePoint(surfaceOptions, latitude, longitude);
|
|
13561
|
+
const localHorizontal = sampleContinuousOctopusSurfacePoint(surfaceOptions, latitude, longitude + 0.018);
|
|
13562
|
+
const localVertical = sampleContinuousOctopusSurfacePoint(surfaceOptions, latitude + 0.018, longitude);
|
|
13563
|
+
const sceneCenterPoint = transformScenePoint(localCenter, center, rotationX, rotationY);
|
|
13564
|
+
if (sceneCenterPoint.z <= center.z - size * 0.012) {
|
|
13565
|
+
return;
|
|
13566
|
+
}
|
|
13567
|
+
const projectedCenterPoint = projectScenePoint(sceneCenterPoint, size, sceneCenterX, sceneCenterY);
|
|
13568
|
+
const projectedHorizontalPoint = projectScenePoint(transformScenePoint(localHorizontal, center, rotationX, rotationY), size, sceneCenterX, sceneCenterY);
|
|
13569
|
+
const projectedVerticalPoint = projectScenePoint(transformScenePoint(localVertical, center, rotationX, rotationY), size, sceneCenterX, sceneCenterY);
|
|
13570
|
+
const horizontalRadius = clampNumber$1(Math.hypot(projectedHorizontalPoint.x - projectedCenterPoint.x, projectedHorizontalPoint.y - projectedCenterPoint.y) *
|
|
13571
|
+
radiusScale *
|
|
13572
|
+
0.74, size * 0.003, size * 0.018);
|
|
13573
|
+
const verticalRadius = clampNumber$1(Math.hypot(projectedVerticalPoint.x - projectedCenterPoint.x, projectedVerticalPoint.y - projectedCenterPoint.y) *
|
|
13574
|
+
radiusScale *
|
|
13575
|
+
0.52, size * 0.0024, size * 0.014);
|
|
13576
|
+
const rotation = Math.atan2(projectedHorizontalPoint.y - projectedCenterPoint.y, projectedHorizontalPoint.x - projectedCenterPoint.x);
|
|
13577
|
+
context.save();
|
|
13578
|
+
context.translate(projectedCenterPoint.x, projectedCenterPoint.y);
|
|
13579
|
+
context.rotate(rotation);
|
|
13580
|
+
context.beginPath();
|
|
13581
|
+
context.ellipse(0, 0, horizontalRadius, verticalRadius, 0, 0, Math.PI * 2);
|
|
13582
|
+
context.fillStyle = `${palette.highlight}73`;
|
|
13583
|
+
context.fill();
|
|
13584
|
+
context.strokeStyle = `${palette.highlight}99`;
|
|
13585
|
+
context.lineWidth = Math.max(0.7, size * 0.0028);
|
|
13586
|
+
context.stroke();
|
|
13587
|
+
context.restore();
|
|
13588
|
+
}
|
|
13589
|
+
/**
|
|
13590
|
+
* Resolves a signed angular distance from the source longitude to the target longitude.
|
|
13591
|
+
*
|
|
13592
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13593
|
+
*/
|
|
13594
|
+
function resolveSignedAngularDistance(sourceLongitude, targetLongitude) {
|
|
13595
|
+
return Math.atan2(Math.sin(targetLongitude - sourceLongitude), Math.cos(targetLongitude - sourceLongitude));
|
|
13596
|
+
}
|
|
13597
|
+
/**
|
|
13598
|
+
* Smoothly maps a value between two bounds into `[0, 1]`.
|
|
13599
|
+
*
|
|
13600
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13601
|
+
*/
|
|
13602
|
+
function smoothStep(edgeStart, edgeEnd, value) {
|
|
13603
|
+
const progress = clampNumber$1((value - edgeStart) / (edgeEnd - edgeStart), 0, 1);
|
|
13604
|
+
return progress * progress * (3 - 2 * progress);
|
|
13605
|
+
}
|
|
13606
|
+
|
|
13061
13607
|
/* eslint-disable no-magic-numbers */
|
|
13062
13608
|
/**
|
|
13063
13609
|
* Octopus avatar visual.
|
|
@@ -13828,6 +14374,7 @@
|
|
|
13828
14374
|
octopus3AvatarVisual,
|
|
13829
14375
|
octopus3dAvatarVisual,
|
|
13830
14376
|
octopus3d2AvatarVisual,
|
|
14377
|
+
octopus3d3AvatarVisual,
|
|
13831
14378
|
asciiOctopusAvatarVisual,
|
|
13832
14379
|
minecraftAvatarVisual,
|
|
13833
14380
|
minecraft2AvatarVisual,
|
|
@@ -33839,6 +34386,14 @@
|
|
|
33839
34386
|
* Idle timeout after completion marker to capture trailing output.
|
|
33840
34387
|
*/
|
|
33841
34388
|
const CODEX_COMPLETION_IDLE_MS = 60 * 1000;
|
|
34389
|
+
/**
|
|
34390
|
+
* Number of seconds in one hour.
|
|
34391
|
+
*/
|
|
34392
|
+
const SECONDS_PER_HOUR = 60 * 60;
|
|
34393
|
+
/**
|
|
34394
|
+
* Poll interval used while waiting for the next rate-limit retry so pause requests can be honored promptly.
|
|
34395
|
+
*/
|
|
34396
|
+
const RATE_LIMIT_BACKOFF_POLL_MS = 1000;
|
|
33842
34397
|
/**
|
|
33843
34398
|
* Maximum delay between retries while rate-limited.
|
|
33844
34399
|
*/
|
|
@@ -33858,8 +34413,8 @@
|
|
|
33858
34413
|
*/
|
|
33859
34414
|
function formatDelay(delayMs) {
|
|
33860
34415
|
const totalSeconds = Math.max(0, Math.round(delayMs / 1000));
|
|
33861
|
-
const hours = Math.floor(totalSeconds /
|
|
33862
|
-
const minutes = Math.floor((totalSeconds %
|
|
34416
|
+
const hours = Math.floor(totalSeconds / SECONDS_PER_HOUR);
|
|
34417
|
+
const minutes = Math.floor((totalSeconds % SECONDS_PER_HOUR) / 60);
|
|
33863
34418
|
const seconds = totalSeconds % 60;
|
|
33864
34419
|
const parts = [];
|
|
33865
34420
|
if (hours > 0) {
|
|
@@ -33900,6 +34455,7 @@
|
|
|
33900
34455
|
* Runs the Codex prompt in a temporary script and waits for completion output.
|
|
33901
34456
|
*/
|
|
33902
34457
|
async runPrompt(options) {
|
|
34458
|
+
var _a;
|
|
33903
34459
|
const scriptContent = buildCodexScript({
|
|
33904
34460
|
prompt: options.prompt,
|
|
33905
34461
|
projectPath: options.projectPath,
|
|
@@ -33910,7 +34466,14 @@
|
|
|
33910
34466
|
allowCredits: this.options.allowCredits,
|
|
33911
34467
|
codexCommand: this.options.codexCommand,
|
|
33912
34468
|
});
|
|
33913
|
-
|
|
34469
|
+
for (let retryIndex = 0;; retryIndex++) {
|
|
34470
|
+
if (retryIndex > 0) {
|
|
34471
|
+
await ((_a = options.waitForPauseCheckpoint) === null || _a === void 0 ? void 0 : _a.call(options, {
|
|
34472
|
+
checkpointLabel: 'retrying the OpenAI Codex model call after rate limit',
|
|
34473
|
+
phase: 'running',
|
|
34474
|
+
statusMessage: 'Retrying OpenAI Codex after rate limit',
|
|
34475
|
+
}));
|
|
34476
|
+
}
|
|
33914
34477
|
try {
|
|
33915
34478
|
const output = await $runGoScriptUntilMarkerIdle({
|
|
33916
34479
|
scriptPath: options.scriptPath,
|
|
@@ -33937,11 +34500,29 @@
|
|
|
33937
34500
|
const retryIndex = this.rateLimitBackoff.retryCount;
|
|
33938
34501
|
const summary = extractFailureSummary(details);
|
|
33939
34502
|
console.warn(colors__default["default"].yellow(`[codex] Rate limit/quota detected (${summary}). Retry #${retryIndex} in ${formatDelay(delayMs)} at ${retryAt}.`));
|
|
33940
|
-
await
|
|
34503
|
+
await waitForRetryDelay(delayMs, options);
|
|
33941
34504
|
}
|
|
33942
34505
|
}
|
|
33943
34506
|
}
|
|
33944
34507
|
}
|
|
34508
|
+
/**
|
|
34509
|
+
* Waits for the next Codex retry while polling for requested pause checkpoints.
|
|
34510
|
+
*/
|
|
34511
|
+
async function waitForRetryDelay(delayMs, options) {
|
|
34512
|
+
var _a;
|
|
34513
|
+
let remainingDelayMs = delayMs;
|
|
34514
|
+
while (remainingDelayMs > 0) {
|
|
34515
|
+
const remainingDelayLabel = formatDelay(remainingDelayMs);
|
|
34516
|
+
await ((_a = options.waitForPauseCheckpoint) === null || _a === void 0 ? void 0 : _a.call(options, {
|
|
34517
|
+
checkpointLabel: 'the next OpenAI Codex retry after rate limit',
|
|
34518
|
+
phase: 'running',
|
|
34519
|
+
statusMessage: `Waiting ${remainingDelayLabel} before retrying OpenAI Codex`,
|
|
34520
|
+
}));
|
|
34521
|
+
const currentDelayMs = Math.min(RATE_LIMIT_BACKOFF_POLL_MS, remainingDelayMs);
|
|
34522
|
+
await waitFor(currentDelayMs);
|
|
34523
|
+
remainingDelayMs -= currentDelayMs;
|
|
34524
|
+
}
|
|
34525
|
+
}
|
|
33945
34526
|
|
|
33946
34527
|
/**
|
|
33947
34528
|
* Builds the shell script that runs Opencode with the prompt and coding context.
|
|
@@ -34262,6 +34843,10 @@
|
|
|
34262
34843
|
* Maximum amount of verification output sent back to the coding agent as retry feedback.
|
|
34263
34844
|
*/
|
|
34264
34845
|
const MAX_TEST_FEEDBACK_OUTPUT_CHARS = 12000;
|
|
34846
|
+
/**
|
|
34847
|
+
* File extension used by generated shell scripts.
|
|
34848
|
+
*/
|
|
34849
|
+
const SHELL_SCRIPT_EXTENSION = '.sh';
|
|
34265
34850
|
/**
|
|
34266
34851
|
* Runs one coding prompt and, when configured, verifies it with a shell command that can feed failures back.
|
|
34267
34852
|
*/
|
|
@@ -34270,12 +34855,14 @@
|
|
|
34270
34855
|
const normalizedTestCommand = (_a = options.testCommand) === null || _a === void 0 ? void 0 : _a.trim();
|
|
34271
34856
|
if (!normalizedTestCommand) {
|
|
34272
34857
|
(_b = options.onAttemptStarted) === null || _b === void 0 ? void 0 : _b.call(options, 1);
|
|
34858
|
+
await waitForPromptAttemptPauseCheckpoint(options.waitForPauseCheckpoint, options.runner.name, 1);
|
|
34273
34859
|
const result = await options.runner.runPrompt({
|
|
34274
34860
|
prompt: options.prompt,
|
|
34275
34861
|
scriptPath: options.scriptPath,
|
|
34276
34862
|
projectPath: options.projectPath,
|
|
34277
34863
|
logPath: options.logPath,
|
|
34278
34864
|
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
34865
|
+
waitForPauseCheckpoint: options.waitForPauseCheckpoint,
|
|
34279
34866
|
});
|
|
34280
34867
|
return { ...result, attemptCount: 1 };
|
|
34281
34868
|
}
|
|
@@ -34283,13 +34870,16 @@
|
|
|
34283
34870
|
let promptForCurrentAttempt = options.prompt;
|
|
34284
34871
|
for (let attemptCount = 1; attemptCount <= MAX_PROMPT_TEST_ATTEMPTS; attemptCount++) {
|
|
34285
34872
|
(_d = options.onAttemptStarted) === null || _d === void 0 ? void 0 : _d.call(options, attemptCount);
|
|
34873
|
+
await waitForPromptAttemptPauseCheckpoint(options.waitForPauseCheckpoint, options.runner.name, attemptCount);
|
|
34286
34874
|
const result = await options.runner.runPrompt({
|
|
34287
34875
|
prompt: promptForCurrentAttempt,
|
|
34288
34876
|
scriptPath: options.scriptPath,
|
|
34289
34877
|
projectPath: options.projectPath,
|
|
34290
34878
|
logPath: options.logPath,
|
|
34291
34879
|
preserveArtifactsOnSuccess: options.preserveArtifactsOnSuccess,
|
|
34880
|
+
waitForPauseCheckpoint: options.waitForPauseCheckpoint,
|
|
34292
34881
|
});
|
|
34882
|
+
await waitForVerificationPauseCheckpoint(options.waitForPauseCheckpoint, normalizedTestCommand, attemptCount);
|
|
34293
34883
|
console.info(colors__default["default"].gray(`Running verification command after attempt #${attemptCount}: ${normalizedTestCommand}`));
|
|
34294
34884
|
try {
|
|
34295
34885
|
await runPromptTestCommandExecutor({
|
|
@@ -34323,6 +34913,44 @@
|
|
|
34323
34913
|
}
|
|
34324
34914
|
throw new Error('Unexpected prompt verification state.');
|
|
34325
34915
|
}
|
|
34916
|
+
/**
|
|
34917
|
+
* Waits for a pause checkpoint immediately before one model attempt begins.
|
|
34918
|
+
*/
|
|
34919
|
+
async function waitForPromptAttemptPauseCheckpoint(waitForPauseCheckpoint, runnerName, attemptCount) {
|
|
34920
|
+
await (waitForPauseCheckpoint === null || waitForPauseCheckpoint === void 0 ? void 0 : waitForPauseCheckpoint({
|
|
34921
|
+
checkpointLabel: buildPromptAttemptPauseLabel(runnerName, attemptCount),
|
|
34922
|
+
phase: 'running',
|
|
34923
|
+
statusMessage: buildPromptAttemptStatusMessage(runnerName, attemptCount),
|
|
34924
|
+
}));
|
|
34925
|
+
}
|
|
34926
|
+
/**
|
|
34927
|
+
* Waits for a pause checkpoint immediately before one verification command begins.
|
|
34928
|
+
*/
|
|
34929
|
+
async function waitForVerificationPauseCheckpoint(waitForPauseCheckpoint, testCommand, attemptCount) {
|
|
34930
|
+
await (waitForPauseCheckpoint === null || waitForPauseCheckpoint === void 0 ? void 0 : waitForPauseCheckpoint({
|
|
34931
|
+
checkpointLabel: buildVerificationPauseLabel(attemptCount),
|
|
34932
|
+
phase: 'verifying',
|
|
34933
|
+
statusMessage: `Running verification after attempt #${attemptCount}: ${testCommand}`,
|
|
34934
|
+
}));
|
|
34935
|
+
}
|
|
34936
|
+
/**
|
|
34937
|
+
* Builds the human-readable pause label used before one runner attempt begins.
|
|
34938
|
+
*/
|
|
34939
|
+
function buildPromptAttemptPauseLabel(runnerName, attemptCount) {
|
|
34940
|
+
return `calling ${runnerName} (attempt ${attemptCount})`;
|
|
34941
|
+
}
|
|
34942
|
+
/**
|
|
34943
|
+
* Builds the status line shown while one runner attempt is about to start.
|
|
34944
|
+
*/
|
|
34945
|
+
function buildPromptAttemptStatusMessage(runnerName, attemptCount) {
|
|
34946
|
+
return `Calling ${runnerName} (attempt ${attemptCount})`;
|
|
34947
|
+
}
|
|
34948
|
+
/**
|
|
34949
|
+
* Builds the human-readable pause label used before one verification command begins.
|
|
34950
|
+
*/
|
|
34951
|
+
function buildVerificationPauseLabel(attemptCount) {
|
|
34952
|
+
return `running verification after attempt #${attemptCount}`;
|
|
34953
|
+
}
|
|
34326
34954
|
/**
|
|
34327
34955
|
* Builds one feedback block appended to the next coding attempt after tests fail.
|
|
34328
34956
|
*/
|
|
@@ -34372,8 +35000,8 @@
|
|
|
34372
35000
|
* Derives a dedicated temp-script path for verification commands.
|
|
34373
35001
|
*/
|
|
34374
35002
|
function buildPromptTestScriptPath(scriptPath) {
|
|
34375
|
-
if (scriptPath.toLowerCase().endsWith(
|
|
34376
|
-
return `${scriptPath.slice(0, -
|
|
35003
|
+
if (scriptPath.toLowerCase().endsWith(SHELL_SCRIPT_EXTENSION)) {
|
|
35004
|
+
return `${scriptPath.slice(0, -SHELL_SCRIPT_EXTENSION.length)}.test.sh`;
|
|
34377
35005
|
}
|
|
34378
35006
|
return `${scriptPath}.test.sh`;
|
|
34379
35007
|
}
|
|
@@ -34564,7 +35192,7 @@
|
|
|
34564
35192
|
const totalWidth = Math.max(MIN_FRAME_WIDTH, Math.min(options.terminalWidth, MAX_FRAME_WIDTH));
|
|
34565
35193
|
const isPromptActive = options.phase === 'running' || options.phase === 'verifying' || options.phase === 'loading';
|
|
34566
35194
|
const promptStatusPrefix = isPromptActive ? `${colors__default["default"].yellow(`${options.spinner} `)}` : '';
|
|
34567
|
-
const pausePresentation = buildPausePresentation(options.phase, options.pauseState, options.statusMessage);
|
|
35195
|
+
const pausePresentation = buildPausePresentation(options.phase, options.pauseState, options.pauseTargetLabel, options.statusMessage);
|
|
34568
35196
|
const sessionLines = buildSessionLines(options, totalWidth, pausePresentation);
|
|
34569
35197
|
const agentStatusLines = buildAgentStatusTableLines(options, totalWidth);
|
|
34570
35198
|
const currentTaskLines = options.currentPromptLabel
|
|
@@ -68804,8 +69432,12 @@
|
|
|
68804
69432
|
const commitMessage = buildCommitMessage(nextPrompt.file, nextPrompt.section);
|
|
68805
69433
|
const codexPrompt = appendCoderContext(buildCodexPrompt(nextPrompt.file, nextPrompt.section), resolvedCoderContext);
|
|
68806
69434
|
const scriptPath = buildScriptPath(nextPrompt.file, nextPrompt.section);
|
|
68807
|
-
await waitForRequestedPause();
|
|
68808
69435
|
setPromptRoundRunningState({ isRichUiEnabled, promptLabel, scriptPath, uiHandle });
|
|
69436
|
+
await waitForRequestedPause({
|
|
69437
|
+
checkpointLabel: 'preparing the current prompt execution',
|
|
69438
|
+
phase: 'running',
|
|
69439
|
+
statusMessage: 'Preparing prompt execution',
|
|
69440
|
+
});
|
|
68809
69441
|
const promptExecutionStartedDate = moment__default["default"]();
|
|
68810
69442
|
let attemptCount = 1;
|
|
68811
69443
|
const roundChangedFilesSnapshot = options.normalizeLineEndings
|
|
@@ -68826,11 +69458,8 @@
|
|
|
68826
69458
|
onAttemptStarted: (nextAttemptCount) => {
|
|
68827
69459
|
attemptCount = nextAttemptCount;
|
|
68828
69460
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setAttempt(nextAttemptCount);
|
|
68829
|
-
if (nextAttemptCount > 1) {
|
|
68830
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Retrying (attempt ${nextAttemptCount})`);
|
|
68831
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('verifying');
|
|
68832
|
-
}
|
|
68833
69461
|
},
|
|
69462
|
+
waitForPauseCheckpoint: waitForRequestedPause,
|
|
68834
69463
|
});
|
|
68835
69464
|
await finalizeSuccessfulPromptRound({
|
|
68836
69465
|
options,
|
|
@@ -68844,6 +69473,7 @@
|
|
|
68844
69473
|
isRichUiEnabled,
|
|
68845
69474
|
progressDisplay,
|
|
68846
69475
|
uiHandle,
|
|
69476
|
+
waitForRequestedPause,
|
|
68847
69477
|
});
|
|
68848
69478
|
}
|
|
68849
69479
|
catch (error) {
|
|
@@ -68856,6 +69486,7 @@
|
|
|
68856
69486
|
options,
|
|
68857
69487
|
roundChangedFilesSnapshot,
|
|
68858
69488
|
uiHandle,
|
|
69489
|
+
waitForRequestedPause,
|
|
68859
69490
|
});
|
|
68860
69491
|
throw error;
|
|
68861
69492
|
}
|
|
@@ -68879,9 +69510,13 @@
|
|
|
68879
69510
|
* Finalizes a successful prompt round, including prompt bookkeeping and commit flow.
|
|
68880
69511
|
*/
|
|
68881
69512
|
async function finalizeSuccessfulPromptRound(options) {
|
|
68882
|
-
const { options: runOptions, nextPrompt, runnerMetadata, promptExecutionStartedDate, result, commitMessage, logPath, roundChangedFilesSnapshot, isRichUiEnabled, progressDisplay, uiHandle, } = options;
|
|
69513
|
+
const { options: runOptions, nextPrompt, runnerMetadata, promptExecutionStartedDate, result, commitMessage, logPath, roundChangedFilesSnapshot, isRichUiEnabled, progressDisplay, uiHandle, waitForRequestedPause, } = options;
|
|
68883
69514
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
68884
|
-
|
|
69515
|
+
await waitForRequestedPause({
|
|
69516
|
+
checkpointLabel: 'recording the successful prompt result',
|
|
69517
|
+
phase: 'running',
|
|
69518
|
+
statusMessage: 'Recording prompt result',
|
|
69519
|
+
});
|
|
68885
69520
|
markPromptDone(nextPrompt.file, nextPrompt.section, result.usage, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, result.attemptCount);
|
|
68886
69521
|
await writePromptFile(nextPrompt.file);
|
|
68887
69522
|
await normalizeLineEndingsForCurrentRound(runOptions, roundChangedFilesSnapshot);
|
|
@@ -68893,22 +69528,42 @@
|
|
|
68893
69528
|
progressDisplay,
|
|
68894
69529
|
uiHandle,
|
|
68895
69530
|
});
|
|
69531
|
+
await waitForRequestedPause({
|
|
69532
|
+
checkpointLabel: 'committing the successful changes',
|
|
69533
|
+
phase: 'running',
|
|
69534
|
+
statusMessage: 'Committing changes',
|
|
69535
|
+
});
|
|
68896
69536
|
await commitChanges(commitMessage, {
|
|
68897
69537
|
autoPush: runOptions.autoPush,
|
|
68898
69538
|
// Keep the live runtime log out of default commits because it is deleted after a successful round.
|
|
68899
69539
|
excludePaths: runOptions.preserveLogs ? undefined : [logPath],
|
|
68900
69540
|
});
|
|
68901
69541
|
}
|
|
69542
|
+
else {
|
|
69543
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Leaving changes uncommitted');
|
|
69544
|
+
}
|
|
69545
|
+
if (runOptions.autoMigrate) {
|
|
69546
|
+
await waitForRequestedPause({
|
|
69547
|
+
checkpointLabel: 'running testing-server auto-migration',
|
|
69548
|
+
phase: 'running',
|
|
69549
|
+
statusMessage: 'Running testing-server auto-migration',
|
|
69550
|
+
});
|
|
69551
|
+
}
|
|
68902
69552
|
await runPostPromptAutoMigrationIfEnabled(runOptions);
|
|
68903
69553
|
}
|
|
68904
69554
|
/**
|
|
68905
69555
|
* Finalizes a failed prompt round, persisting prompt failure metadata before rethrowing.
|
|
68906
69556
|
*/
|
|
68907
69557
|
async function finalizeFailedPromptRound(options) {
|
|
68908
|
-
const { nextPrompt, runnerMetadata, promptExecutionStartedDate, attemptCount, error, options: runOptions, roundChangedFilesSnapshot, uiHandle, } = options;
|
|
69558
|
+
const { nextPrompt, runnerMetadata, promptExecutionStartedDate, attemptCount, error, options: runOptions, roundChangedFilesSnapshot, uiHandle, waitForRequestedPause, } = options;
|
|
68909
69559
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.stopCapturingAgentOutput();
|
|
68910
69560
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('error');
|
|
68911
69561
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.addError(error instanceof Error ? error.message : String(error));
|
|
69562
|
+
await waitForRequestedPause({
|
|
69563
|
+
checkpointLabel: 'recording the prompt failure',
|
|
69564
|
+
phase: 'error',
|
|
69565
|
+
statusMessage: 'Recording prompt failure',
|
|
69566
|
+
});
|
|
68912
69567
|
markPromptFailed(nextPrompt.file, nextPrompt.section, runnerMetadata.runnerName, runnerMetadata.modelName, promptExecutionStartedDate, attemptCount);
|
|
68913
69568
|
await writePromptFile(nextPrompt.file);
|
|
68914
69569
|
await writePromptErrorLog({
|
|
@@ -68943,6 +69598,8 @@
|
|
|
68943
69598
|
}
|
|
68944
69599
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
|
|
68945
69600
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
69601
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('running');
|
|
69602
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Committing changes');
|
|
68946
69603
|
}
|
|
68947
69604
|
/**
|
|
68948
69605
|
* Formats commit preview lines for the rich terminal UI.
|
|
@@ -69015,11 +69672,21 @@
|
|
|
69015
69672
|
let hasShownUpcomingTasks = false;
|
|
69016
69673
|
let hasWaitedForStart = false;
|
|
69017
69674
|
while (just(true)) {
|
|
69018
|
-
|
|
69675
|
+
if (options.autoPull && !options.dryRun) {
|
|
69676
|
+
await waitForRequestedPause({
|
|
69677
|
+
checkpointLabel: 'pulling the latest repository changes',
|
|
69678
|
+
phase: 'loading',
|
|
69679
|
+
statusMessage: 'Pulling latest changes...',
|
|
69680
|
+
});
|
|
69681
|
+
}
|
|
69019
69682
|
await pullLatestChangesIfEnabled({
|
|
69020
69683
|
options,
|
|
69021
69684
|
isRichUiEnabled,
|
|
69022
|
-
|
|
69685
|
+
});
|
|
69686
|
+
await waitForRequestedPause({
|
|
69687
|
+
checkpointLabel: 'loading prompts',
|
|
69688
|
+
phase: 'loading',
|
|
69689
|
+
statusMessage: 'Loading prompts...',
|
|
69023
69690
|
});
|
|
69024
69691
|
const promptQueueSnapshot = await loadPromptQueueSnapshot({
|
|
69025
69692
|
options,
|
|
@@ -69049,6 +69716,11 @@
|
|
|
69049
69716
|
uiHandle,
|
|
69050
69717
|
});
|
|
69051
69718
|
if (!options.ignoreGitChanges) {
|
|
69719
|
+
await waitForRequestedPause({
|
|
69720
|
+
checkpointLabel: 'checking the git working tree',
|
|
69721
|
+
phase: 'loading',
|
|
69722
|
+
statusMessage: 'Checking the working tree...',
|
|
69723
|
+
});
|
|
69052
69724
|
await ensureWorkingTreeClean();
|
|
69053
69725
|
}
|
|
69054
69726
|
await runPromptRound({
|
|
@@ -69097,12 +69769,10 @@
|
|
|
69097
69769
|
* Pulls the latest repository state before loading prompts when the feature is enabled.
|
|
69098
69770
|
*/
|
|
69099
69771
|
async function pullLatestChangesIfEnabled(options) {
|
|
69100
|
-
const { options: runOptions, isRichUiEnabled
|
|
69772
|
+
const { options: runOptions, isRichUiEnabled } = options;
|
|
69101
69773
|
if (!runOptions.autoPull || runOptions.dryRun) {
|
|
69102
69774
|
return;
|
|
69103
69775
|
}
|
|
69104
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('loading');
|
|
69105
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Pulling latest changes...');
|
|
69106
69776
|
if (!isRichUiEnabled) {
|
|
69107
69777
|
console.info(colors__default["default"].gray('Pulling latest changes before the next prompt...'));
|
|
69108
69778
|
}
|
|
@@ -69126,22 +69796,26 @@
|
|
|
69126
69796
|
*/
|
|
69127
69797
|
function createPauseWaiter(options) {
|
|
69128
69798
|
const { isRichUiEnabled, progressDisplay, uiHandle } = options;
|
|
69129
|
-
return async () => {
|
|
69799
|
+
return async (checkpoint) => {
|
|
69800
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase(checkpoint.phase);
|
|
69801
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(checkpoint.statusMessage);
|
|
69802
|
+
announcePauseTargetLabel(checkpoint.checkpointLabel);
|
|
69130
69803
|
await checkPause({
|
|
69131
69804
|
silent: isRichUiEnabled,
|
|
69132
69805
|
onPaused: () => {
|
|
69133
69806
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.pauseTimer();
|
|
69134
69807
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
69135
69808
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('paused');
|
|
69136
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(
|
|
69809
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Paused before ${checkpoint.checkpointLabel}`);
|
|
69137
69810
|
},
|
|
69138
69811
|
onResumed: () => {
|
|
69139
69812
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
|
|
69140
69813
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
69141
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase(
|
|
69142
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(
|
|
69814
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase(checkpoint.phase);
|
|
69815
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(checkpoint.statusMessage);
|
|
69143
69816
|
},
|
|
69144
69817
|
});
|
|
69818
|
+
resetPauseTargetLabel();
|
|
69145
69819
|
};
|
|
69146
69820
|
}
|
|
69147
69821
|
/**
|
|
@@ -69186,11 +69860,7 @@
|
|
|
69186
69860
|
*/
|
|
69187
69861
|
async function loadPromptQueueSnapshot(options) {
|
|
69188
69862
|
const { options: runOptions, isRichUiEnabled, progressDisplay, uiHandle } = options;
|
|
69189
|
-
|
|
69190
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentScriptPath(undefined);
|
|
69191
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('loading');
|
|
69192
|
-
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage('Loading prompts...');
|
|
69193
|
-
}
|
|
69863
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setCurrentScriptPath(undefined);
|
|
69194
69864
|
const promptFiles = await loadPromptFiles(PROMPTS_DIR$1);
|
|
69195
69865
|
const stats = summarizePrompts(promptFiles, runOptions.priority);
|
|
69196
69866
|
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.update(stats);
|