@promptbook/cli 0.112.0-117 → 0.112.0-119
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/src/app/agents/[agentName]/chat/AgentChatSidebarDefault.tsx +5 -6
- package/apps/agents-server/src/app/api/page-preview/check/route.ts +31 -0
- package/apps/agents-server/src/app/api/page-preview/screenshot/route.ts +57 -0
- package/apps/agents-server/src/app/api/upload/route.ts +10 -1
- package/apps/agents-server/src/app/s3/[first]/[second]/[hash]/[filename]/route.ts +52 -0
- package/apps/agents-server/src/database/$provideClientSql.ts +37 -0
- package/apps/agents-server/src/database/$provideSupabaseForServer.ts +41 -0
- package/apps/agents-server/src/tools/$provideCdnForServer.ts +24 -0
- package/apps/agents-server/src/utils/cdn/classes/DigitalOceanSpaces.ts +30 -2
- package/apps/agents-server/src/utils/cdn/utils/getUserFileCdnKey.ts +10 -3
- package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +17 -7
- package/apps/agents-server/src/utils/iframe/checkIfUrlCanBeEmbedded.ts +68 -0
- package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +17 -7
- package/apps/agents-server/src/utils/userChat/createImmediateUserChatAnswerModelRequirements.ts +11 -0
- package/apps/agents-server/src/utils/userChat/listUserChats.ts +5 -7
- package/esm/index.es.js +442 -66
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/parseDuration.d.ts +19 -0
- package/esm/src/_packages/node.index.d.ts +10 -0
- package/esm/src/book-3.0/BookNodeAgentSource.d.ts +1 -1
- package/esm/src/book-3.0/CliAgent.d.ts +7 -2
- package/esm/src/book-3.0/cliAgentEnv.d.ts +33 -0
- package/esm/src/book-components/BookEditor/BookEditor.d.ts +1 -1
- package/esm/src/book-components/BookEditor/BookEditorForClient.d.ts +1 -1
- package/esm/src/book-components/Chat/Chat/CitationIframePreview.d.ts +20 -0
- package/esm/src/book-components/_common/Dropdown/Dropdown.d.ts +1 -1
- package/esm/src/book-components/_common/MenuHoisting/MenuHoistingContext.d.ts +1 -1
- package/esm/src/book-components/_common/Modal/Modal.d.ts +1 -1
- package/esm/src/book-components/icons/AboutIcon.d.ts +1 -1
- package/esm/src/book-components/icons/DownloadIcon.d.ts +1 -1
- package/esm/src/book-components/icons/ExitFullscreenIcon.d.ts +1 -1
- package/esm/src/book-components/icons/FullscreenIcon.d.ts +1 -1
- package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +2 -18
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/_packages/node.index.ts +10 -0
- package/src/avatars/avatarAnimationScheduler.ts +33 -2
- package/src/avatars/visuals/fractalAvatarVisual.ts +5 -4
- package/src/avatars/visuals/minecraft2AvatarVisual.ts +16 -11
- package/src/avatars/visuals/minecraftAvatarVisual.ts +21 -7
- package/src/avatars/visuals/octopus3d2AvatarVisual.ts +69 -17
- package/src/avatars/visuals/octopus3d3AvatarVisual.ts +81 -18
- package/src/avatars/visuals/octopus3dAvatarVisual.ts +69 -17
- package/src/book-3.0/Book.ts +3 -1
- package/src/book-3.0/BookNodeAgentSource.ts +2 -2
- package/src/book-3.0/CliAgent.ts +84 -6
- package/src/book-3.0/LiteAgent.ts +1 -1
- package/src/book-3.0/cliAgentEnv.ts +46 -0
- package/src/book-components/BookEditor/BookEditor.tsx +6 -6
- package/src/book-components/BookEditor/BookEditorForClient.tsx +1 -1
- package/src/book-components/Chat/Chat/Chat.module.css +45 -0
- package/src/book-components/Chat/Chat/ChatCitationModal.tsx +2 -2
- package/src/book-components/Chat/Chat/CitationIframePreview.tsx +83 -0
- package/src/book-components/_common/Dropdown/Dropdown.tsx +1 -1
- package/src/book-components/_common/MenuHoisting/MenuHoistingContext.tsx +1 -1
- package/src/book-components/_common/Modal/Modal.tsx +1 -1
- package/src/book-components/icons/AboutIcon.tsx +1 -1
- package/src/book-components/icons/DownloadIcon.tsx +1 -1
- package/src/book-components/icons/ExitFullscreenIcon.tsx +1 -1
- package/src/book-components/icons/FullscreenIcon.tsx +1 -1
- package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +31 -1
- package/src/cli/cli-commands/coder/run.ts +28 -3
- package/src/cli/cli-commands/common/promptRunnerCliOptions.ts +9 -29
- package/src/execution/createPipelineExecutor/getKnowledgeForTask.ts +1 -1
- package/src/llm-providers/openai/OpenAiAgentKitExecutionToolsToolBuilder.ts +1 -1
- package/src/llm-providers/openai/OpenAiAssistantExecutionToolsToolRunner.ts +1 -1
- package/src/llm-providers/openai/OpenAiVectorStoreKnowledgeSourcePreparer.ts +1 -1
- package/src/other/templates/getTemplatesPipelineCollection.ts +734 -711
- package/src/scripting/javascript/JavascriptEvalExecutionTools.ts +1 -1
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +442 -66
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/parseDuration.d.ts +19 -0
- package/umd/src/_packages/node.index.d.ts +10 -0
- package/umd/src/book-3.0/BookNodeAgentSource.d.ts +1 -1
- package/umd/src/book-3.0/CliAgent.d.ts +7 -2
- package/umd/src/book-3.0/cliAgentEnv.d.ts +33 -0
- package/umd/src/book-components/BookEditor/BookEditor.d.ts +1 -1
- package/umd/src/book-components/BookEditor/BookEditorForClient.d.ts +1 -1
- package/umd/src/book-components/Chat/Chat/CitationIframePreview.d.ts +20 -0
- package/umd/src/book-components/_common/Dropdown/Dropdown.d.ts +1 -1
- package/umd/src/book-components/_common/MenuHoisting/MenuHoistingContext.d.ts +1 -1
- package/umd/src/book-components/_common/Modal/Modal.d.ts +1 -1
- package/umd/src/book-components/icons/AboutIcon.d.ts +1 -1
- package/umd/src/book-components/icons/DownloadIcon.d.ts +1 -1
- package/umd/src/book-components/icons/ExitFullscreenIcon.d.ts +1 -1
- package/umd/src/book-components/icons/FullscreenIcon.d.ts +1 -1
- package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +2 -18
- package/umd/src/version.d.ts +1 -1
package/esm/index.es.js
CHANGED
|
@@ -58,7 +58,7 @@ const BOOK_LANGUAGE_VERSION = '2.0.0';
|
|
|
58
58
|
* @generated
|
|
59
59
|
* @see https://github.com/webgptorg/promptbook
|
|
60
60
|
*/
|
|
61
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
61
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-119';
|
|
62
62
|
/**
|
|
63
63
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
64
64
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -1740,12 +1740,13 @@ function parseThinkingLevel(thinkingLevelValue) {
|
|
|
1740
1740
|
}
|
|
1741
1741
|
// Note: [🟡] Code for CLI command [run](src/cli/cli-commands/coder/run.ts) should never be published outside of `@promptbook/cli`
|
|
1742
1742
|
|
|
1743
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
1743
1744
|
/**
|
|
1744
|
-
*
|
|
1745
|
+
* All CLI harness names supported by `CliAgent` and `ptbk agent exec`.
|
|
1745
1746
|
*
|
|
1746
|
-
* @
|
|
1747
|
+
* @public exported from `@promptbook/node`
|
|
1747
1748
|
*/
|
|
1748
|
-
const
|
|
1749
|
+
const CLI_AGENT_HARNESS_NAMES = [
|
|
1749
1750
|
'openai-codex',
|
|
1750
1751
|
'github-copilot',
|
|
1751
1752
|
'cline',
|
|
@@ -1754,23 +1755,33 @@ const PROMPT_RUNNER_HARNESS_NAMES = [
|
|
|
1754
1755
|
'gemini',
|
|
1755
1756
|
];
|
|
1756
1757
|
/**
|
|
1757
|
-
* Environment variable used as the default runner identifier when `--harness` is omitted
|
|
1758
|
+
* Environment variable used as the default runner identifier when `--harness` is omitted or not set in `CliAgent`.
|
|
1758
1759
|
*
|
|
1759
|
-
*
|
|
1760
|
+
* Set this to one of the harness names (`openai-codex`, `github-copilot`, `cline`, `claude-code`, `opencode`, `gemini`)
|
|
1761
|
+
* so that `CliAgent` and `ptbk agent exec` can run without an explicit `harness` option.
|
|
1762
|
+
*
|
|
1763
|
+
* @public exported from `@promptbook/node`
|
|
1760
1764
|
*/
|
|
1761
1765
|
const PTBK_HARNESS_ENV = 'PTBK_HARNESS';
|
|
1762
1766
|
/**
|
|
1763
|
-
* Environment variable used as the default runner model when `--model` is omitted
|
|
1767
|
+
* Environment variable used as the default runner model when `--model` is omitted or not set in `CliAgent`.
|
|
1764
1768
|
*
|
|
1765
|
-
* @
|
|
1769
|
+
* @public exported from `@promptbook/node`
|
|
1766
1770
|
*/
|
|
1767
1771
|
const PTBK_MODEL_ENV = 'PTBK_MODEL';
|
|
1768
1772
|
/**
|
|
1769
|
-
* Environment variable used as the default
|
|
1773
|
+
* Environment variable used as the default thinking level when `--thinking-level` is omitted or not set in `CliAgent`.
|
|
1770
1774
|
*
|
|
1771
|
-
* @
|
|
1775
|
+
* @public exported from `@promptbook/node`
|
|
1772
1776
|
*/
|
|
1773
1777
|
const PTBK_THINKING_LEVEL_ENV = 'PTBK_THINKING_LEVEL';
|
|
1778
|
+
|
|
1779
|
+
/**
|
|
1780
|
+
* Runner identifiers supported by Promptbook CLI agent orchestration commands.
|
|
1781
|
+
*
|
|
1782
|
+
* @private internal utility of `promptbookCli`
|
|
1783
|
+
*/
|
|
1784
|
+
const PROMPT_RUNNER_HARNESS_NAMES = CLI_AGENT_HARNESS_NAMES;
|
|
1774
1785
|
/**
|
|
1775
1786
|
* Description block shared by runner-backed CLI commands.
|
|
1776
1787
|
*
|
|
@@ -3261,6 +3272,16 @@ const AGENTS_SERVER_NEXT_BUILD_ID_FILENAME = 'BUILD_ID';
|
|
|
3261
3272
|
* @private internal constant of `ptbk agents-server`
|
|
3262
3273
|
*/
|
|
3263
3274
|
const DEFAULT_AGENTS_SERVER_NEXT_DIST_DIRECTORY_NAME = '.next';
|
|
3275
|
+
/**
|
|
3276
|
+
* Node.js heap size limit (in MiB) injected into `NODE_OPTIONS` for the Next.js production build.
|
|
3277
|
+
*
|
|
3278
|
+
* Next.js webpack peaks at ~1.9 GiB on a fresh install; the Node.js default cap is ~1.7 GiB,
|
|
3279
|
+
* which causes an OOM crash on first-run VPS installations where swap is the primary resource.
|
|
3280
|
+
* Raising the limit lets the build complete on the first attempt.
|
|
3281
|
+
*
|
|
3282
|
+
* @private internal constant of `ptbk agents-server`
|
|
3283
|
+
*/
|
|
3284
|
+
const AGENTS_SERVER_BUILD_MAX_OLD_SPACE_MIB = 4096;
|
|
3264
3285
|
/**
|
|
3265
3286
|
* Environment variable passed to the bundled Next app so webpack can resolve dependencies
|
|
3266
3287
|
* installed beside `ptbk` even when the app sources are materialized into a project cache.
|
|
@@ -3658,7 +3679,10 @@ async function runNextBuild(options) {
|
|
|
3658
3679
|
var _a, _b;
|
|
3659
3680
|
const buildProcess = spawn(process.execPath, [options.nextCliPath, 'build'], {
|
|
3660
3681
|
cwd: options.appPath,
|
|
3661
|
-
env:
|
|
3682
|
+
env: {
|
|
3683
|
+
...options.environment,
|
|
3684
|
+
NODE_OPTIONS: mergeNodeOptionsWithHeapSize(options.environment.NODE_OPTIONS, AGENTS_SERVER_BUILD_MAX_OLD_SPACE_MIB),
|
|
3685
|
+
},
|
|
3662
3686
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
3663
3687
|
});
|
|
3664
3688
|
(_a = buildProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (chunk) => {
|
|
@@ -3677,6 +3701,16 @@ async function runNextBuild(options) {
|
|
|
3677
3701
|
});
|
|
3678
3702
|
});
|
|
3679
3703
|
}
|
|
3704
|
+
/**
|
|
3705
|
+
* Prepends `--max-old-space-size=<mib>` to `NODE_OPTIONS` unless the caller already set one.
|
|
3706
|
+
*/
|
|
3707
|
+
function mergeNodeOptionsWithHeapSize(existingNodeOptions, maxOldSpaceMib) {
|
|
3708
|
+
if (existingNodeOptions !== undefined && /--max-old-space-size[= ]/u.test(existingNodeOptions)) {
|
|
3709
|
+
return existingNodeOptions;
|
|
3710
|
+
}
|
|
3711
|
+
const heapFlag = `--max-old-space-size=${maxOldSpaceMib}`;
|
|
3712
|
+
return existingNodeOptions ? `${heapFlag} ${existingNodeOptions}` : heapFlag;
|
|
3713
|
+
}
|
|
3680
3714
|
/**
|
|
3681
3715
|
* Sends one Next build output chunk through the caller handler or to the foreground terminal.
|
|
3682
3716
|
*/
|
|
@@ -5124,6 +5158,7 @@ function createCoderRunOptionsForAgent(options) {
|
|
|
5124
5158
|
noUi: options.noUi,
|
|
5125
5159
|
thinkingLevel: options.thinkingLevel,
|
|
5126
5160
|
waitForUser: false,
|
|
5161
|
+
waitBetweenPrompts: 0,
|
|
5127
5162
|
noCommit: options.noCommit,
|
|
5128
5163
|
ignoreGitChanges: options.ignoreGitChanges,
|
|
5129
5164
|
normalizeLineEndings: options.normalizeLineEndings,
|
|
@@ -10816,21 +10851,22 @@ function getPointBounds(points) {
|
|
|
10816
10851
|
* @private helper of `fractalAvatarVisual`
|
|
10817
10852
|
*/
|
|
10818
10853
|
function drawDragonCurveLayer(context, points, options) {
|
|
10819
|
-
const {
|
|
10854
|
+
const { primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
|
|
10820
10855
|
const firstPoint = points[0];
|
|
10821
10856
|
const lastPoint = points[points.length - 1];
|
|
10822
10857
|
const ribbonGradient = context.createLinearGradient(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y);
|
|
10823
10858
|
ribbonGradient.addColorStop(0, `${primaryColor}f2`);
|
|
10824
10859
|
ribbonGradient.addColorStop(0.5, `${secondaryColor}e6`);
|
|
10825
10860
|
ribbonGradient.addColorStop(1, `${tertiaryColor}f2`);
|
|
10861
|
+
// Approximate the blurred shadow stroke with a wider semi-transparent stroke instead of
|
|
10862
|
+
// context.filter blur, which triggers a costly software rasterization pass every frame.
|
|
10826
10863
|
context.save();
|
|
10827
10864
|
context.beginPath();
|
|
10828
10865
|
tracePolyline(context, points);
|
|
10829
|
-
context.strokeStyle = `${shadowColor}
|
|
10830
|
-
context.lineWidth = strokeWidth *
|
|
10866
|
+
context.strokeStyle = `${shadowColor}48`;
|
|
10867
|
+
context.lineWidth = strokeWidth * 4.5;
|
|
10831
10868
|
context.lineJoin = 'round';
|
|
10832
10869
|
context.lineCap = 'round';
|
|
10833
|
-
context.filter = `blur(${size * 0.022}px)`;
|
|
10834
10870
|
context.stroke();
|
|
10835
10871
|
context.restore();
|
|
10836
10872
|
context.beginPath();
|
|
@@ -11414,11 +11450,23 @@ function drawMinecraftBackdrop(context, size, palette, sceneCenterX, spotlightY,
|
|
|
11414
11450
|
* @private helper of `minecraft2AvatarVisual`
|
|
11415
11451
|
*/
|
|
11416
11452
|
function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
|
|
11453
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.03;
|
|
11454
|
+
const cy = size * 0.85 + Math.sin(timeMs / 880) * size * 0.01;
|
|
11455
|
+
const rx = size * (0.16 + interaction.intensity * 0.015);
|
|
11456
|
+
const ry = size * 0.055;
|
|
11457
|
+
// Radial gradient approximates the blurry ellipse shadow without context.filter blur.
|
|
11417
11458
|
context.save();
|
|
11418
|
-
context.
|
|
11419
|
-
context.
|
|
11459
|
+
context.translate(cx, cy);
|
|
11460
|
+
context.scale(1, ry / rx);
|
|
11461
|
+
const blurRadius = rx * 1.4;
|
|
11462
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
11463
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
11464
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
11465
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
11466
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
11467
|
+
context.fillStyle = shadowGradient;
|
|
11420
11468
|
context.beginPath();
|
|
11421
|
-
context.
|
|
11469
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
11422
11470
|
context.fill();
|
|
11423
11471
|
context.restore();
|
|
11424
11472
|
}
|
|
@@ -11642,13 +11690,27 @@ const minecraftAvatarVisual = {
|
|
|
11642
11690
|
spotlight.addColorStop(1, `${palette.highlight}00`);
|
|
11643
11691
|
context.fillStyle = spotlight;
|
|
11644
11692
|
context.fillRect(0, 0, size, size);
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11693
|
+
{
|
|
11694
|
+
// Radial gradient approximates the blurry ellipse shadow without context.filter blur.
|
|
11695
|
+
const cx = size * 0.5;
|
|
11696
|
+
const cy = size * 0.86;
|
|
11697
|
+
const rx = size * 0.2;
|
|
11698
|
+
const ry = size * 0.06;
|
|
11699
|
+
const blurRadius = rx * 1.4;
|
|
11700
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
11701
|
+
shadowGradient.addColorStop(0, 'rgba(0,0,0,0.28)');
|
|
11702
|
+
shadowGradient.addColorStop(0.45, 'rgba(0,0,0,0.14)');
|
|
11703
|
+
shadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.05)');
|
|
11704
|
+
shadowGradient.addColorStop(1, 'rgba(0,0,0,0)');
|
|
11705
|
+
context.save();
|
|
11706
|
+
context.translate(cx, cy);
|
|
11707
|
+
context.scale(1, ry / rx);
|
|
11708
|
+
context.fillStyle = shadowGradient;
|
|
11709
|
+
context.beginPath();
|
|
11710
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
11711
|
+
context.fill();
|
|
11712
|
+
context.restore();
|
|
11713
|
+
}
|
|
11652
11714
|
drawVoxelCuboid(context, {
|
|
11653
11715
|
x: bodyX,
|
|
11654
11716
|
y: bodyY,
|
|
@@ -12700,6 +12762,35 @@ const LIGHT_DIRECTION$2 = normalizeVector3({
|
|
|
12700
12762
|
y: -0.62,
|
|
12701
12763
|
z: 0.94,
|
|
12702
12764
|
});
|
|
12765
|
+
/**
|
|
12766
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
12767
|
+
*
|
|
12768
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
12769
|
+
*/
|
|
12770
|
+
const octopus3dStableStateCache = new WeakMap();
|
|
12771
|
+
/**
|
|
12772
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
12773
|
+
*
|
|
12774
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
12775
|
+
*/
|
|
12776
|
+
function getOctopus3dStableState(createRandom) {
|
|
12777
|
+
const cached = octopus3dStableStateCache.get(createRandom);
|
|
12778
|
+
if (cached !== undefined) {
|
|
12779
|
+
return cached;
|
|
12780
|
+
}
|
|
12781
|
+
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
12782
|
+
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
12783
|
+
const leftEyePhaseOffset = eyeRandom() * 0.6;
|
|
12784
|
+
const rightEyePhaseOffset = eyeRandom() * 0.6;
|
|
12785
|
+
const state = {
|
|
12786
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
12787
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
12788
|
+
leftEyePhaseOffset,
|
|
12789
|
+
rightEyePhaseOffset,
|
|
12790
|
+
};
|
|
12791
|
+
octopus3dStableStateCache.set(createRandom, state);
|
|
12792
|
+
return state;
|
|
12793
|
+
}
|
|
12703
12794
|
/**
|
|
12704
12795
|
* Proper 3D Octopus visual built from projected organic meshes and tentacles.
|
|
12705
12796
|
*
|
|
@@ -12712,10 +12803,7 @@ const octopus3dAvatarVisual = {
|
|
|
12712
12803
|
isAnimated: true,
|
|
12713
12804
|
supportsPointerTracking: true,
|
|
12714
12805
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
12715
|
-
const morphologyProfile =
|
|
12716
|
-
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
12717
|
-
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
12718
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
12806
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
|
|
12719
12807
|
const sceneCenterX = size * 0.5;
|
|
12720
12808
|
const sceneCenterY = size * 0.56;
|
|
12721
12809
|
const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
|
|
@@ -12812,12 +12900,12 @@ const octopus3dAvatarVisual = {
|
|
|
12812
12900
|
x: -faceEyeSpacing,
|
|
12813
12901
|
y: faceEyeYOffset,
|
|
12814
12902
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
12815
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase +
|
|
12903
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
12816
12904
|
drawProjectedOrganicEye(context, {
|
|
12817
12905
|
x: faceEyeSpacing,
|
|
12818
12906
|
y: faceEyeYOffset,
|
|
12819
12907
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
12820
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 +
|
|
12908
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
12821
12909
|
drawProjectedOrganicMouth(context, [
|
|
12822
12910
|
{
|
|
12823
12911
|
x: -mouthHalfWidth,
|
|
@@ -12861,14 +12949,28 @@ function drawOctopus3dAtmosphere(context, size, palette, sceneCenterX, sceneCent
|
|
|
12861
12949
|
/**
|
|
12862
12950
|
* Draws the soft ground shadow below the octopus.
|
|
12863
12951
|
*
|
|
12952
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
12953
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
12954
|
+
*
|
|
12864
12955
|
* @private helper of `octopus3dAvatarVisual`
|
|
12865
12956
|
*/
|
|
12866
12957
|
function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
|
|
12958
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.04;
|
|
12959
|
+
const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
|
|
12960
|
+
const rx = size * (0.18 + interaction.intensity * 0.02);
|
|
12961
|
+
const ry = size * 0.06;
|
|
12867
12962
|
context.save();
|
|
12868
|
-
context.
|
|
12869
|
-
context.
|
|
12963
|
+
context.translate(cx, cy);
|
|
12964
|
+
context.scale(1, ry / rx);
|
|
12965
|
+
const blurRadius = rx * 1.4;
|
|
12966
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
12967
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
12968
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
12969
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
12970
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
12971
|
+
context.fillStyle = shadowGradient;
|
|
12870
12972
|
context.beginPath();
|
|
12871
|
-
context.
|
|
12973
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
12872
12974
|
context.fill();
|
|
12873
12975
|
context.restore();
|
|
12874
12976
|
}
|
|
@@ -13099,6 +13201,35 @@ const LIGHT_DIRECTION$1 = normalizeVector3({
|
|
|
13099
13201
|
y: -0.6,
|
|
13100
13202
|
z: 0.98,
|
|
13101
13203
|
});
|
|
13204
|
+
/**
|
|
13205
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
13206
|
+
*
|
|
13207
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
13208
|
+
*/
|
|
13209
|
+
const octopus3d2StableStateCache = new WeakMap();
|
|
13210
|
+
/**
|
|
13211
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
13212
|
+
*
|
|
13213
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
13214
|
+
*/
|
|
13215
|
+
function getOctopus3d2StableState(createRandom) {
|
|
13216
|
+
const cached = octopus3d2StableStateCache.get(createRandom);
|
|
13217
|
+
if (cached !== undefined) {
|
|
13218
|
+
return cached;
|
|
13219
|
+
}
|
|
13220
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
13221
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
13222
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
13223
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
13224
|
+
const state = {
|
|
13225
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
13226
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
13227
|
+
leftEyePhaseOffset,
|
|
13228
|
+
rightEyePhaseOffset,
|
|
13229
|
+
};
|
|
13230
|
+
octopus3d2StableStateCache.set(createRandom, state);
|
|
13231
|
+
return state;
|
|
13232
|
+
}
|
|
13102
13233
|
/**
|
|
13103
13234
|
* Octopus 3D 2 avatar visual.
|
|
13104
13235
|
*
|
|
@@ -13111,10 +13242,7 @@ const octopus3d2AvatarVisual = {
|
|
|
13111
13242
|
isAnimated: true,
|
|
13112
13243
|
supportsPointerTracking: true,
|
|
13113
13244
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
13114
|
-
const morphologyProfile =
|
|
13115
|
-
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
13116
|
-
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
13117
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
13245
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3d2StableState(createRandom);
|
|
13118
13246
|
const sceneCenterX = size * 0.5;
|
|
13119
13247
|
const sceneCenterY = size * 0.575;
|
|
13120
13248
|
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
@@ -13167,8 +13295,8 @@ const octopus3d2AvatarVisual = {
|
|
|
13167
13295
|
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
13168
13296
|
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
13169
13297
|
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
13170
|
-
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase +
|
|
13171
|
-
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 +
|
|
13298
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
13299
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
13172
13300
|
drawProjectedOrganicMouth(context, [
|
|
13173
13301
|
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
13174
13302
|
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
@@ -13197,14 +13325,28 @@ function drawBlobbyOctopusAtmosphere(context, size, palette, sceneCenterX, scene
|
|
|
13197
13325
|
/**
|
|
13198
13326
|
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
13199
13327
|
*
|
|
13328
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
13329
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
13330
|
+
*
|
|
13200
13331
|
* @private helper of `octopus3d2AvatarVisual`
|
|
13201
13332
|
*/
|
|
13202
13333
|
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
13334
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
13335
|
+
const cy = size * 0.88 + Math.sin(timeMs / 940) * size * 0.008;
|
|
13336
|
+
const rx = size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018);
|
|
13337
|
+
const ry = size * 0.062;
|
|
13203
13338
|
context.save();
|
|
13204
|
-
context.
|
|
13205
|
-
context.
|
|
13339
|
+
context.translate(cx, cy);
|
|
13340
|
+
context.scale(1, ry / rx);
|
|
13341
|
+
const blurRadius = rx * 1.4;
|
|
13342
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
13343
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
13344
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
13345
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
13346
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
13347
|
+
context.fillStyle = shadowGradient;
|
|
13206
13348
|
context.beginPath();
|
|
13207
|
-
context.
|
|
13349
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
13208
13350
|
context.fill();
|
|
13209
13351
|
context.restore();
|
|
13210
13352
|
}
|
|
@@ -13360,6 +13502,40 @@ const LIGHT_DIRECTION = normalizeVector3({
|
|
|
13360
13502
|
* @private helper of `octopus3d3AvatarVisual`
|
|
13361
13503
|
*/
|
|
13362
13504
|
const OCTOPUS_TENTACLE_COUNT = 8;
|
|
13505
|
+
/**
|
|
13506
|
+
* Cache keyed by the `createRandom` factory reference, which is stable for the lifetime of one
|
|
13507
|
+
* mounted `<Avatar/>` component (created inside `resolveAvatarRenderDefinition` and held in a
|
|
13508
|
+
* React `useMemo`). Using a `WeakMap` ensures the entry is collected when the component unmounts.
|
|
13509
|
+
*
|
|
13510
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13511
|
+
*/
|
|
13512
|
+
const stableStateCache = new WeakMap();
|
|
13513
|
+
/**
|
|
13514
|
+
* Returns the stable per-avatar state, computing it on first access and returning the cached
|
|
13515
|
+
* result on every subsequent call within the same `<Avatar/>` mount.
|
|
13516
|
+
*
|
|
13517
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13518
|
+
*/
|
|
13519
|
+
function getOctopus3d3StableState(createRandom) {
|
|
13520
|
+
const cached = stableStateCache.get(createRandom);
|
|
13521
|
+
if (cached !== undefined) {
|
|
13522
|
+
return cached;
|
|
13523
|
+
}
|
|
13524
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
13525
|
+
const animationRandom = createRandom('octopus3d3-animation-profile');
|
|
13526
|
+
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
13527
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
13528
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
13529
|
+
const state = {
|
|
13530
|
+
morphologyProfile,
|
|
13531
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
13532
|
+
leftEyePhaseOffset,
|
|
13533
|
+
rightEyePhaseOffset,
|
|
13534
|
+
tentacleProfiles: createContinuousTentacleProfiles(createRandom, morphologyProfile),
|
|
13535
|
+
};
|
|
13536
|
+
stableStateCache.set(createRandom, state);
|
|
13537
|
+
return state;
|
|
13538
|
+
}
|
|
13363
13539
|
/**
|
|
13364
13540
|
* Octopus 3D 3 avatar visual.
|
|
13365
13541
|
*
|
|
@@ -13372,11 +13548,7 @@ const octopus3d3AvatarVisual = {
|
|
|
13372
13548
|
isAnimated: true,
|
|
13373
13549
|
supportsPointerTracking: true,
|
|
13374
13550
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
13375
|
-
const morphologyProfile =
|
|
13376
|
-
const animationRandom = createRandom('octopus3d3-animation-profile');
|
|
13377
|
-
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
13378
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
13379
|
-
const tentacleProfiles = createContinuousTentacleProfiles(createRandom, morphologyProfile);
|
|
13551
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles } = getOctopus3d3StableState(createRandom);
|
|
13380
13552
|
const sceneCenterX = size * 0.5;
|
|
13381
13553
|
const sceneCenterY = size * 0.535;
|
|
13382
13554
|
const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
|
|
@@ -13453,8 +13625,8 @@ const octopus3d3AvatarVisual = {
|
|
|
13453
13625
|
size,
|
|
13454
13626
|
palette,
|
|
13455
13627
|
});
|
|
13456
|
-
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase +
|
|
13457
|
-
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 +
|
|
13628
|
+
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
13629
|
+
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
13458
13630
|
drawProjectedOrganicMouth(context, [
|
|
13459
13631
|
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
13460
13632
|
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
@@ -13505,14 +13677,30 @@ function drawContinuousOctopusAtmosphere(context, size, palette, sceneCenterX, s
|
|
|
13505
13677
|
/**
|
|
13506
13678
|
* Draws the soft lower shadow that anchors the octopus in the avatar frame.
|
|
13507
13679
|
*
|
|
13680
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
13681
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
13682
|
+
*
|
|
13508
13683
|
* @private helper of `octopus3d3AvatarVisual`
|
|
13509
13684
|
*/
|
|
13510
13685
|
function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
13686
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
13687
|
+
const cy = size * 0.9 + Math.sin(timeMs / 980) * size * 0.007;
|
|
13688
|
+
const rx = size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02);
|
|
13689
|
+
const ry = size * 0.06;
|
|
13690
|
+
// Scale the context so that drawing a circle produces the correct ellipse aspect ratio,
|
|
13691
|
+
// then fill with a radial gradient that approximates the blurry edge without context.filter.
|
|
13511
13692
|
context.save();
|
|
13512
|
-
context.
|
|
13513
|
-
context.
|
|
13693
|
+
context.translate(cx, cy);
|
|
13694
|
+
context.scale(1, ry / rx);
|
|
13695
|
+
const blurRadius = rx * 1.4;
|
|
13696
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
13697
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
13698
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
13699
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
13700
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
13701
|
+
context.fillStyle = shadowGradient;
|
|
13514
13702
|
context.beginPath();
|
|
13515
|
-
context.
|
|
13703
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
13516
13704
|
context.fill();
|
|
13517
13705
|
context.restore();
|
|
13518
13706
|
}
|
|
@@ -28737,14 +28925,50 @@ function buildAgentMessageCommitMessage(messageFile) {
|
|
|
28737
28925
|
* Builds the prompt sent to the selected coding runner for one queued user-thread book.
|
|
28738
28926
|
*/
|
|
28739
28927
|
function buildAgentMessagePrompt(messageRelativePath, agentSystemMessage) {
|
|
28740
|
-
|
|
28741
|
-
|
|
28928
|
+
return spaceTrim$1((block) => `
|
|
28929
|
+
# Answer 1 user question
|
|
28742
28930
|
|
|
28743
|
-
|
|
28744
|
-
|
|
28745
|
-
|
|
28746
|
-
|
|
28747
|
-
|
|
28931
|
+
- Read \`${messageRelativePath}\` and answer the most recent \`MESSAGE @User\`
|
|
28932
|
+
- Only change the queued message file by appending one new \`MESSAGE @Agent\` block
|
|
28933
|
+
- Do not modify any other file in the repository
|
|
28934
|
+
|
|
28935
|
+
## Rules for the answering
|
|
28936
|
+
|
|
28937
|
+
## Formatting
|
|
28938
|
+
|
|
28939
|
+
- You can use Markdown formatting in the messages like **bold** or *italic*
|
|
28940
|
+
|
|
28941
|
+
## Sources and citations
|
|
28942
|
+
|
|
28943
|
+
Mark sources and citations like this "【https://example.com/document123.pdf 】"
|
|
28944
|
+
|
|
28945
|
+
At the same time, you can write sources naturally in the text of the answers
|
|
28946
|
+
|
|
28947
|
+
For example:
|
|
28948
|
+
|
|
28949
|
+
> According to paragraph §745b, the fee can be waived for a person over 65 years old. 【https://praha13.cz/2026/paragraph-745.doc】
|
|
28950
|
+
|
|
28951
|
+
- "paragraph §745b" fits naturally in the text.
|
|
28952
|
+
- "【https://praha13.cz/2026/paragraph-745.doc】" The exact format of the quote is important for further processing of the answer.
|
|
28953
|
+
- The "【" and "】" symbols are used to mark the source and will be parsed, inside should be valid URL used as a source for the answer.
|
|
28954
|
+
|
|
28955
|
+
## Quick buttons
|
|
28956
|
+
|
|
28957
|
+
If there is a meaningful follow-up procedure, use quick buttons at the end of the answer:
|
|
28958
|
+
|
|
28959
|
+
\`\`\`
|
|
28960
|
+
How big is the contract you are posting?
|
|
28961
|
+
|
|
28962
|
+
[Up to 50,000 CZK](?message=We are posting an order up to 50,000 CZK)
|
|
28963
|
+
[Up to 100,000 CZK](?message=We are posting an order up to 100,000 CZK)
|
|
28964
|
+
[Over 100,000 CZK](?message=We are posting an order over 100,000 CZK)
|
|
28965
|
+
\`\`\`
|
|
28966
|
+
|
|
28967
|
+
|
|
28968
|
+
## This is how you should behave
|
|
28969
|
+
|
|
28970
|
+
${block(agentSystemMessage)}
|
|
28971
|
+
`);
|
|
28748
28972
|
}
|
|
28749
28973
|
|
|
28750
28974
|
/**
|
|
@@ -35889,7 +36113,9 @@ function parseBookMessageHeader(line) {
|
|
|
35889
36113
|
* @private internal utility of `Book`
|
|
35890
36114
|
*/
|
|
35891
36115
|
function parseCommitmentHeader(line) {
|
|
35892
|
-
|
|
36116
|
+
// Require at least 2 characters in the first keyword word to avoid treating common
|
|
36117
|
+
// single-letter words (e.g. "V" in Czech, "I" or "A" in English) as commitment headers.
|
|
36118
|
+
const match = /^([A-Z][A-Z0-9]+(?: [A-Z0-9]+)*)(?:\s+(.*))?$/u.exec(line);
|
|
35893
36119
|
if (!match) {
|
|
35894
36120
|
return null;
|
|
35895
36121
|
}
|
|
@@ -39303,6 +39529,57 @@ function listDefaultCoderProjectPromptTemplateDisplayPaths() {
|
|
|
39303
39529
|
// Note: [🟡] Code for CLI command [init](src/cli/cli-commands/coder/init.ts) should never be published outside of `@promptbook/cli`
|
|
39304
39530
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
39305
39531
|
|
|
39532
|
+
/**
|
|
39533
|
+
* Pattern that matches durations like "1h", "30m", "5s", "1h30m", "1h30m5s".
|
|
39534
|
+
*/
|
|
39535
|
+
const DURATION_PATTERN = /^(?:(\d+)h)?(?:(\d+)m(?:in)?)?(?:(\d+)s)?$/;
|
|
39536
|
+
/**
|
|
39537
|
+
* Parses a human-readable duration string into milliseconds.
|
|
39538
|
+
*
|
|
39539
|
+
* Supported formats: `Xh`, `Xm`, `Xs`, and combinations like `1h30m`, `1h30m5s`.
|
|
39540
|
+
*
|
|
39541
|
+
* @returns Duration in milliseconds
|
|
39542
|
+
* @throws When the string does not match any supported format
|
|
39543
|
+
*
|
|
39544
|
+
* @private internal utility of `ptbk coder run`
|
|
39545
|
+
*/
|
|
39546
|
+
function parseDuration(durationString) {
|
|
39547
|
+
var _a, _b, _c;
|
|
39548
|
+
const trimmed = durationString.trim();
|
|
39549
|
+
if (!trimmed) {
|
|
39550
|
+
throw new Error(`Invalid duration: empty string. Expected a format like "1h", "30m", "5s", or combinations like "1h30m".`);
|
|
39551
|
+
}
|
|
39552
|
+
const match = trimmed.match(DURATION_PATTERN);
|
|
39553
|
+
if (!match || (match[1] === undefined && match[2] === undefined && match[3] === undefined)) {
|
|
39554
|
+
throw new Error(`Invalid duration: "${durationString}". Expected a format like "1h", "30m", "5s", or combinations like "1h30m5s".`);
|
|
39555
|
+
}
|
|
39556
|
+
const hours = parseInt((_a = match[1]) !== null && _a !== void 0 ? _a : '0', 10);
|
|
39557
|
+
const minutes = parseInt((_b = match[2]) !== null && _b !== void 0 ? _b : '0', 10);
|
|
39558
|
+
const seconds = parseInt((_c = match[3]) !== null && _c !== void 0 ? _c : '0', 10);
|
|
39559
|
+
return (hours * 3600 + minutes * 60 + seconds) * 1000;
|
|
39560
|
+
}
|
|
39561
|
+
/**
|
|
39562
|
+
* Formats a duration in milliseconds into a compact human-readable string.
|
|
39563
|
+
*
|
|
39564
|
+
* Examples: `3600000` → `"1h"`, `90000` → `"1m 30s"`, `5000` → `"5s"`.
|
|
39565
|
+
*
|
|
39566
|
+
* @private internal utility of `ptbk coder run`
|
|
39567
|
+
*/
|
|
39568
|
+
function formatDurationMs(ms) {
|
|
39569
|
+
const totalSeconds = Math.ceil(ms / 1000);
|
|
39570
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
39571
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
39572
|
+
const seconds = totalSeconds % 60;
|
|
39573
|
+
const parts = [];
|
|
39574
|
+
if (hours > 0)
|
|
39575
|
+
parts.push(`${hours}h`);
|
|
39576
|
+
if (minutes > 0)
|
|
39577
|
+
parts.push(`${minutes}m`);
|
|
39578
|
+
if (seconds > 0 || parts.length === 0)
|
|
39579
|
+
parts.push(`${seconds}s`);
|
|
39580
|
+
return parts.join(' ');
|
|
39581
|
+
}
|
|
39582
|
+
|
|
39306
39583
|
/**
|
|
39307
39584
|
* Initializes `coder run` command for Promptbook CLI utilities
|
|
39308
39585
|
*
|
|
@@ -39335,7 +39612,13 @@ function $initializeCoderRunCommand(program) {
|
|
|
39335
39612
|
command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
|
|
39336
39613
|
addPromptRunnerExecutionOptions(command);
|
|
39337
39614
|
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
|
|
39338
|
-
command.option('--
|
|
39615
|
+
command.option('--wait [duration]', spaceTrim$1(`
|
|
39616
|
+
Wait between prompt rounds.
|
|
39617
|
+
Without a value (default): waits for user confirmation before each prompt (interactive mode).
|
|
39618
|
+
With a duration like 1h, 30m, 5s: waits that long between prompts to avoid hitting rate limits of the harness.
|
|
39619
|
+
`), true);
|
|
39620
|
+
// Note: --no-wait disables the default interactive wait-for-user behaviour
|
|
39621
|
+
command.option('--no-wait', 'Skip all waiting between prompts and run non-interactively');
|
|
39339
39622
|
command.option('--auto-migrate', 'Run testing-server database migrations automatically after each successfully processed prompt');
|
|
39340
39623
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
39341
39624
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
@@ -39344,10 +39627,23 @@ function $initializeCoderRunCommand(program) {
|
|
|
39344
39627
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
39345
39628
|
isAgentRequired: !dryRun,
|
|
39346
39629
|
});
|
|
39630
|
+
// [1] Parse the --wait option:
|
|
39631
|
+
// true (default or --wait without value): wait for user confirmation
|
|
39632
|
+
// false (--no-wait): no waiting at all
|
|
39633
|
+
// string (--wait 1h): wait that long between prompt rounds
|
|
39634
|
+
let waitForUser = false;
|
|
39635
|
+
let waitBetweenPrompts = 0;
|
|
39636
|
+
if (wait === true) {
|
|
39637
|
+
waitForUser = true;
|
|
39638
|
+
}
|
|
39639
|
+
else if (typeof wait === 'string' && wait !== '') {
|
|
39640
|
+
waitBetweenPrompts = parseDuration(wait);
|
|
39641
|
+
}
|
|
39347
39642
|
// Convert commander options to RunOptions format
|
|
39348
39643
|
const runOptions = {
|
|
39349
39644
|
dryRun,
|
|
39350
|
-
waitForUser
|
|
39645
|
+
waitForUser,
|
|
39646
|
+
waitBetweenPrompts,
|
|
39351
39647
|
noCommit: runnerOptions.noCommit,
|
|
39352
39648
|
ignoreGitChanges: runnerOptions.ignoreGitChanges,
|
|
39353
39649
|
agentName: runnerOptions.agentName,
|
|
@@ -58186,7 +58482,7 @@ class OpenAiVectorStoreKnowledgeSourcePreparer {
|
|
|
58186
58482
|
return { skippedReason: 'invalid_data_url' };
|
|
58187
58483
|
}
|
|
58188
58484
|
return {
|
|
58189
|
-
file: new File([parsed.buffer], parsed.filename, {
|
|
58485
|
+
file: new File([new Uint8Array(parsed.buffer)], parsed.filename, {
|
|
58190
58486
|
type: parsed.mimeType,
|
|
58191
58487
|
}),
|
|
58192
58488
|
sizeBytes: parsed.buffer.length,
|
|
@@ -62790,6 +63086,7 @@ function createPromptRunnerOptions(options) {
|
|
|
62790
63086
|
noUi: options.noUi,
|
|
62791
63087
|
thinkingLevel: options.thinkingLevel,
|
|
62792
63088
|
waitForUser: false,
|
|
63089
|
+
waitBetweenPrompts: 0,
|
|
62793
63090
|
noCommit: true,
|
|
62794
63091
|
ignoreGitChanges: true,
|
|
62795
63092
|
normalizeLineEndings: false,
|
|
@@ -68324,7 +68621,7 @@ var findRefactorCandidates$1 = /*#__PURE__*/Object.freeze({
|
|
|
68324
68621
|
/**
|
|
68325
68622
|
* CLI usage text for this script.
|
|
68326
68623
|
*/
|
|
68327
|
-
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--harness <harness-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--preserve-logs] [--no-ui] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--allow-credits] [--auto-migrate] [--allow-destructive-auto-migrate] [--no-wait] [--no-commit] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push] [--auto-pull]';
|
|
68624
|
+
const USAGE = 'Usage: run-codex-prompts [--dry-run] [--harness <harness-name>] [--model <model>] [--context <context-or-file>] [--test <test-command...>] [--preserve-logs] [--no-ui] [--thinking-level <thinking-level>] [--priority <minimum-priority>] [--allow-credits] [--auto-migrate] [--allow-destructive-auto-migrate] [--wait [duration]] [--no-wait] [--no-commit] [--ignore-git-changes] [--no-normalize-line-endings] [--auto-push] [--auto-pull]';
|
|
68328
68625
|
/**
|
|
68329
68626
|
* Top-level flags supported by this command.
|
|
68330
68627
|
*/
|
|
@@ -68341,6 +68638,7 @@ const KNOWN_OPTION_FLAGS = new Set([
|
|
|
68341
68638
|
'--allow-credits',
|
|
68342
68639
|
'--auto-migrate',
|
|
68343
68640
|
'--allow-destructive-auto-migrate',
|
|
68641
|
+
'--wait',
|
|
68344
68642
|
'--no-wait',
|
|
68345
68643
|
'--no-commit',
|
|
68346
68644
|
'--ignore-git-changes',
|
|
@@ -68379,6 +68677,22 @@ function parseRunOptions(args) {
|
|
|
68379
68677
|
const allowDestructiveAutoMigrate = args.includes('--allow-destructive-auto-migrate');
|
|
68380
68678
|
const autoPush = args.includes('--auto-push');
|
|
68381
68679
|
const autoPull = args.includes('--auto-pull');
|
|
68680
|
+
// [1] Parse --wait [duration]:
|
|
68681
|
+
// absent or --no-wait: no waiting
|
|
68682
|
+
// --wait (no value): wait for user confirmation
|
|
68683
|
+
// --wait 1h: wait 1h between prompt rounds to avoid rate limits
|
|
68684
|
+
const waitOptionalValue = readOptionalOptionValue(args, '--wait');
|
|
68685
|
+
let waitForUser = false;
|
|
68686
|
+
let waitBetweenPrompts = 0;
|
|
68687
|
+
if (waitOptionalValue === null) {
|
|
68688
|
+
// --wait present without a duration value: interactive mode
|
|
68689
|
+
waitForUser = true;
|
|
68690
|
+
}
|
|
68691
|
+
else if (waitOptionalValue !== undefined) {
|
|
68692
|
+
// --wait <duration>: time-based wait between rounds
|
|
68693
|
+
waitBetweenPrompts = parseDuration(waitOptionalValue);
|
|
68694
|
+
}
|
|
68695
|
+
// --no-wait (or no flag): both waitForUser and waitBetweenPrompts remain false/0
|
|
68382
68696
|
let thinkingLevel;
|
|
68383
68697
|
if (hasTestCommandFlag && testCommand === undefined) {
|
|
68384
68698
|
exitWithUsageError('Missing value for --test. Use a shell command such as `npm run test` and quote it when it contains top-level CLI flags.');
|
|
@@ -68397,7 +68711,8 @@ function parseRunOptions(args) {
|
|
|
68397
68711
|
}
|
|
68398
68712
|
return {
|
|
68399
68713
|
dryRun,
|
|
68400
|
-
waitForUser
|
|
68714
|
+
waitForUser,
|
|
68715
|
+
waitBetweenPrompts,
|
|
68401
68716
|
noCommit,
|
|
68402
68717
|
ignoreGitChanges,
|
|
68403
68718
|
normalizeLineEndings,
|
|
@@ -68416,6 +68731,23 @@ function parseRunOptions(args) {
|
|
|
68416
68731
|
priority,
|
|
68417
68732
|
};
|
|
68418
68733
|
}
|
|
68734
|
+
/**
|
|
68735
|
+
* Reads an optional value for a flag that may appear with or without a following value.
|
|
68736
|
+
*
|
|
68737
|
+
* Returns `undefined` when the flag is absent, `null` when the flag is present but has no value
|
|
68738
|
+
* (the next token is another flag or the end of args), and the value string otherwise.
|
|
68739
|
+
*/
|
|
68740
|
+
function readOptionalOptionValue(args, flag) {
|
|
68741
|
+
if (!args.includes(flag)) {
|
|
68742
|
+
return undefined;
|
|
68743
|
+
}
|
|
68744
|
+
const index = args.indexOf(flag);
|
|
68745
|
+
const nextArg = args[index + 1];
|
|
68746
|
+
if (nextArg === undefined || nextArg.startsWith('-')) {
|
|
68747
|
+
return null;
|
|
68748
|
+
}
|
|
68749
|
+
return nextArg;
|
|
68750
|
+
}
|
|
68419
68751
|
/**
|
|
68420
68752
|
* Reads a value of a CLI option that follows a given flag.
|
|
68421
68753
|
*/
|
|
@@ -70871,6 +71203,7 @@ async function runCodexPrompts(providedOptions) {
|
|
|
70871
71203
|
initializeRunUi(uiHandle, runner.name, actualRunnerModel, options);
|
|
70872
71204
|
let hasShownUpcomingTasks = false;
|
|
70873
71205
|
let hasWaitedForStart = false;
|
|
71206
|
+
let hasRunAtLeastOneRound = false;
|
|
70874
71207
|
while (just(true)) {
|
|
70875
71208
|
if (options.autoPull && !options.dryRun) {
|
|
70876
71209
|
await waitForRequestedPause({
|
|
@@ -70906,6 +71239,16 @@ async function runCodexPrompts(providedOptions) {
|
|
|
70906
71239
|
}
|
|
70907
71240
|
const nextPrompt = promptQueueSnapshot.nextPrompt;
|
|
70908
71241
|
const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section);
|
|
71242
|
+
// Wait between prompt rounds (skipped for the first round)
|
|
71243
|
+
if (hasRunAtLeastOneRound) {
|
|
71244
|
+
await waitBetweenPromptRoundsIfNeeded({
|
|
71245
|
+
options,
|
|
71246
|
+
isRichUiEnabled,
|
|
71247
|
+
progressDisplay,
|
|
71248
|
+
uiHandle,
|
|
71249
|
+
});
|
|
71250
|
+
}
|
|
71251
|
+
hasRunAtLeastOneRound = true;
|
|
70909
71252
|
hasWaitedForStart = await waitForPromptConfirmationIfNeeded({
|
|
70910
71253
|
options,
|
|
70911
71254
|
nextPrompt,
|
|
@@ -71141,6 +71484,39 @@ async function waitForPromptConfirmationIfNeeded(options) {
|
|
|
71141
71484
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
71142
71485
|
return true;
|
|
71143
71486
|
}
|
|
71487
|
+
/**
|
|
71488
|
+
* Countdown update interval for the between-rounds wait display.
|
|
71489
|
+
*/
|
|
71490
|
+
const WAIT_COUNTDOWN_UPDATE_INTERVAL_MS = 30000;
|
|
71491
|
+
/**
|
|
71492
|
+
* Waits the configured time between prompt rounds to avoid hitting harness rate limits.
|
|
71493
|
+
* Does nothing when `waitBetweenPrompts` is zero.
|
|
71494
|
+
*/
|
|
71495
|
+
async function waitBetweenPromptRoundsIfNeeded(options) {
|
|
71496
|
+
const { options: runOptions, isRichUiEnabled, progressDisplay, uiHandle } = options;
|
|
71497
|
+
const { waitBetweenPrompts } = runOptions;
|
|
71498
|
+
if (waitBetweenPrompts <= 0) {
|
|
71499
|
+
return;
|
|
71500
|
+
}
|
|
71501
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.pauseTimer();
|
|
71502
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
71503
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('waiting');
|
|
71504
|
+
let remaining = waitBetweenPrompts;
|
|
71505
|
+
while (remaining > 0) {
|
|
71506
|
+
const statusMessage = `Waiting ${formatDurationMs(remaining)} before next prompt to avoid rate limits...`;
|
|
71507
|
+
if (!isRichUiEnabled) {
|
|
71508
|
+
console.info(colors.gray(statusMessage));
|
|
71509
|
+
}
|
|
71510
|
+
else {
|
|
71511
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(statusMessage);
|
|
71512
|
+
}
|
|
71513
|
+
const sleepMs = Math.min(WAIT_COUNTDOWN_UPDATE_INTERVAL_MS, remaining);
|
|
71514
|
+
await new Promise((resolve) => setTimeout(resolve, sleepMs));
|
|
71515
|
+
remaining -= sleepMs;
|
|
71516
|
+
}
|
|
71517
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
|
|
71518
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
71519
|
+
}
|
|
71144
71520
|
/**
|
|
71145
71521
|
* Stops active displays and prints the git identity tip for real runs.
|
|
71146
71522
|
*/
|