@promptbook/cli 0.112.0-115 → 0.112.0-118
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/utils/externalChatRunner/processExternalUserChatJob.ts +17 -7
- 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 +451 -95
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/parseDuration.d.ts +19 -0
- package/esm/src/_packages/components.index.d.ts +2 -0
- package/esm/src/_packages/node.index.d.ts +20 -0
- package/esm/src/book-3.0/BookNodeAgentSource.d.ts +1 -1
- package/esm/src/book-3.0/CliAgent.d.ts +15 -17
- package/esm/src/book-3.0/agentFolderPaths.d.ts +30 -0
- package/esm/src/book-3.0/cliAgentEnv.d.ts +33 -0
- package/esm/src/book-components/BookEditor/BookEditorBrowserConfig.d.ts +2 -0
- package/esm/src/book-components/BookEditor/BookEditorForClient.d.ts +7 -0
- package/esm/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +9 -0
- package/esm/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +2 -30
- package/esm/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +2 -18
- package/esm/src/scrapers/website/utils/createShowdownConverter.d.ts +2 -2
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/_packages/components.index.ts +2 -0
- package/src/_packages/node.index.ts +20 -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 +87 -71
- package/src/book-3.0/agentFolderPaths.ts +38 -0
- package/src/book-3.0/cliAgentEnv.ts +46 -0
- package/src/book-components/BookEditor/BookEditor.tsx +1 -1
- package/src/book-components/BookEditor/BookEditorAboutPromptbookInformation.tsx +2 -4
- package/src/book-components/BookEditor/BookEditorActionbar.tsx +32 -2
- package/src/book-components/BookEditor/BookEditorBrowserConfig.ts +11 -0
- package/src/book-components/BookEditor/BookEditorForClient.tsx +33 -0
- package/src/book-components/BookEditor/BookEditorMonaco.tsx +1 -1
- package/src/book-components/BookEditor/BookEditorMonacoTokenization.ts +83 -15
- package/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.ts +11 -0
- package/src/book-components/BookEditor/useBookEditorMonacoLanguage.ts +32 -46
- package/src/book-components/BookEditor/useBookEditorMonacoStyles.ts +1 -1
- package/src/book-components/BookEditor/useBookEditorMonacoUploads.ts +1 -1
- package/src/book-components/Chat/utils/renderMarkdown.ts +3 -2
- package/src/cli/cli-commands/agent-folder/agentProjectPaths.ts +15 -35
- package/src/cli/cli-commands/coder/run.ts +28 -3
- package/src/cli/cli-commands/common/promptRunnerCliOptions.ts +9 -29
- package/src/commands/KNOWLEDGE/utils/knowledgeSourceContentToName.ts +2 -2
- package/src/commitments/_common/teamInternalAgentAccess.ts +2 -2
- package/src/formats/csv/CsvFormatParser.ts +4 -4
- package/src/formats/csv/utils/csvParse.ts +2 -2
- package/src/llm-providers/agent/AgentLlmExecutionTools.ts +2 -2
- package/src/llm-providers/agent/AgentLlmExecutionToolsAgentKitRunner.ts +2 -2
- package/src/llm-providers/agent/AgentLlmExecutionToolsOpenAiAssistantRunner.ts +2 -2
- package/src/other/templates/getTemplatesPipelineCollection.ts +712 -807
- package/src/scrapers/_common/utils/getScraperIntermediateSource.ts +2 -2
- package/src/scrapers/website/WebsiteScraper.ts +1 -1
- package/src/scrapers/website/utils/createShowdownConverter.ts +2 -2
- package/src/utils/misc/computeHash.ts +2 -2
- package/src/utils/random/$randomToken.ts +2 -2
- package/src/version.ts +2 -2
- package/src/versions.txt +3 -0
- package/umd/index.umd.js +453 -94
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/parseDuration.d.ts +19 -0
- package/umd/src/_packages/components.index.d.ts +2 -0
- package/umd/src/_packages/node.index.d.ts +20 -0
- package/umd/src/book-3.0/BookNodeAgentSource.d.ts +1 -1
- package/umd/src/book-3.0/CliAgent.d.ts +15 -17
- package/umd/src/book-3.0/agentFolderPaths.d.ts +30 -0
- package/umd/src/book-3.0/cliAgentEnv.d.ts +33 -0
- package/umd/src/book-components/BookEditor/BookEditorBrowserConfig.d.ts +2 -0
- package/umd/src/book-components/BookEditor/BookEditorForClient.d.ts +7 -0
- package/umd/src/book-components/BookEditor/createDeprecatedCommitmentDiagnostics.browser.d.ts +9 -0
- package/umd/src/cli/cli-commands/agent-folder/agentProjectPaths.d.ts +2 -30
- package/umd/src/cli/cli-commands/common/promptRunnerCliOptions.d.ts +2 -18
- package/umd/src/scrapers/website/utils/createShowdownConverter.d.ts +2 -2
- package/umd/src/version.d.ts +1 -1
package/umd/index.umd.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
(function (global, factory) {
|
|
2
2
|
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('colors'), require('commander'), require('spacetrim'), require('fs/promises'), require('path'), require('child_process'), require('crypto'), require('fs'), require('dotenv'), require('moment'), require('waitasecond'), require('prompts'), require('crypto-js/enc-hex'), require('crypto-js/sha256'), require('socket.io-client'), require('jszip'), require('@mozilla/readability'), require('jsdom'), require('crypto-js'), require('showdown'), require('glob-promise'), require('http'), require('express'), require('socket.io'), require('express-openapi-validator'), require('swagger-ui-express'), require('react'), require('react-dom/server'), require('@anthropic-ai/sdk'), require('bottleneck'), require('@azure/openai'), require('rxjs'), require('mime-types'), require('papaparse'), require('@openai/agents'), require('openai'), require('typescript'), require('ignore'), require('readline'), require('url'), require('events'), require('pg'), require('@supabase/supabase-js')) :
|
|
3
3
|
typeof define === 'function' && define.amd ? define(['exports', 'colors', 'commander', 'spacetrim', 'fs/promises', 'path', 'child_process', 'crypto', 'fs', 'dotenv', 'moment', 'waitasecond', 'prompts', 'crypto-js/enc-hex', 'crypto-js/sha256', 'socket.io-client', 'jszip', '@mozilla/readability', 'jsdom', 'crypto-js', 'showdown', 'glob-promise', 'http', 'express', 'socket.io', 'express-openapi-validator', 'swagger-ui-express', 'react', 'react-dom/server', '@anthropic-ai/sdk', 'bottleneck', '@azure/openai', 'rxjs', 'mime-types', 'papaparse', '@openai/agents', 'openai', 'typescript', 'ignore', 'readline', 'url', 'events', 'pg', '@supabase/supabase-js'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global._spaceTrim, global.promises, global.path, global.child_process, global.crypto, global.fs, global.dotenv, global.moment, global.waitasecond, global.prompts, global.hexEncoder, global.sha256, global.socket_ioClient, global.JSZip, global.readability, global.jsdom, global.
|
|
5
|
-
})(this, (function (exports, colors, commander, _spaceTrim, promises, path, child_process, crypto, fs, dotenv, moment, waitasecond, prompts, hexEncoder, sha256, socket_ioClient, JSZip, readability, jsdom,
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["promptbook-cli"] = {}, global.colors, global.commander, global._spaceTrim, global.promises, global.path, global.child_process, global.crypto, global.fs, global.dotenv, global.moment, global.waitasecond, global.prompts, global.hexEncoder, global.sha256, global.socket_ioClient, global.JSZip, global.readability, global.jsdom, global.CryptoJS, global.showdown, global.glob, global.http, global.express, global.socket_io, global.OpenApiValidator, global.swaggerUi, global.react, global.server, global.Anthropic, global.Bottleneck, global.openai, global.rxjs, global.mimeTypes, global.papaparse, global.agents, global.OpenAI, global.ts, global.ignore, global.readline, global.url, global.events, global.pg));
|
|
5
|
+
})(this, (function (exports, colors, commander, _spaceTrim, promises, path, child_process, crypto, fs, dotenv, moment, waitasecond, prompts, hexEncoder, sha256, socket_ioClient, JSZip, readability, jsdom, CryptoJS, showdown, glob, http, express, socket_io, OpenApiValidator, swaggerUi, react, server, Anthropic, Bottleneck, openai, rxjs, mimeTypes, papaparse, agents, OpenAI, ts, ignore, readline, url, events, pg) { 'use strict';
|
|
6
6
|
|
|
7
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
8
8
|
|
|
@@ -34,6 +34,8 @@
|
|
|
34
34
|
var hexEncoder__default = /*#__PURE__*/_interopDefaultLegacy(hexEncoder);
|
|
35
35
|
var sha256__default = /*#__PURE__*/_interopDefaultLegacy(sha256);
|
|
36
36
|
var JSZip__default = /*#__PURE__*/_interopDefaultLegacy(JSZip);
|
|
37
|
+
var CryptoJS__default = /*#__PURE__*/_interopDefaultLegacy(CryptoJS);
|
|
38
|
+
var showdown__default = /*#__PURE__*/_interopDefaultLegacy(showdown);
|
|
37
39
|
var glob__default = /*#__PURE__*/_interopDefaultLegacy(glob);
|
|
38
40
|
var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
|
|
39
41
|
var express__default = /*#__PURE__*/_interopDefaultLegacy(express);
|
|
@@ -41,6 +43,7 @@
|
|
|
41
43
|
var swaggerUi__default = /*#__PURE__*/_interopDefaultLegacy(swaggerUi);
|
|
42
44
|
var Anthropic__default = /*#__PURE__*/_interopDefaultLegacy(Anthropic);
|
|
43
45
|
var Bottleneck__default = /*#__PURE__*/_interopDefaultLegacy(Bottleneck);
|
|
46
|
+
var papaparse__default = /*#__PURE__*/_interopDefaultLegacy(papaparse);
|
|
44
47
|
var OpenAI__default = /*#__PURE__*/_interopDefaultLegacy(OpenAI);
|
|
45
48
|
var ts__namespace = /*#__PURE__*/_interopNamespace(ts);
|
|
46
49
|
var ignore__default = /*#__PURE__*/_interopDefaultLegacy(ignore);
|
|
@@ -60,7 +63,7 @@
|
|
|
60
63
|
* @generated
|
|
61
64
|
* @see https://github.com/webgptorg/promptbook
|
|
62
65
|
*/
|
|
63
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
66
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-118';
|
|
64
67
|
/**
|
|
65
68
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
66
69
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -1742,12 +1745,13 @@
|
|
|
1742
1745
|
}
|
|
1743
1746
|
// Note: [🟡] Code for CLI command [run](src/cli/cli-commands/coder/run.ts) should never be published outside of `@promptbook/cli`
|
|
1744
1747
|
|
|
1748
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
1745
1749
|
/**
|
|
1746
|
-
*
|
|
1750
|
+
* All CLI harness names supported by `CliAgent` and `ptbk agent exec`.
|
|
1747
1751
|
*
|
|
1748
|
-
* @
|
|
1752
|
+
* @public exported from `@promptbook/node`
|
|
1749
1753
|
*/
|
|
1750
|
-
const
|
|
1754
|
+
const CLI_AGENT_HARNESS_NAMES = [
|
|
1751
1755
|
'openai-codex',
|
|
1752
1756
|
'github-copilot',
|
|
1753
1757
|
'cline',
|
|
@@ -1756,23 +1760,33 @@
|
|
|
1756
1760
|
'gemini',
|
|
1757
1761
|
];
|
|
1758
1762
|
/**
|
|
1759
|
-
* Environment variable used as the default runner identifier when `--harness` is omitted
|
|
1763
|
+
* Environment variable used as the default runner identifier when `--harness` is omitted or not set in `CliAgent`.
|
|
1760
1764
|
*
|
|
1761
|
-
*
|
|
1765
|
+
* Set this to one of the harness names (`openai-codex`, `github-copilot`, `cline`, `claude-code`, `opencode`, `gemini`)
|
|
1766
|
+
* so that `CliAgent` and `ptbk agent exec` can run without an explicit `harness` option.
|
|
1767
|
+
*
|
|
1768
|
+
* @public exported from `@promptbook/node`
|
|
1762
1769
|
*/
|
|
1763
1770
|
const PTBK_HARNESS_ENV = 'PTBK_HARNESS';
|
|
1764
1771
|
/**
|
|
1765
|
-
* Environment variable used as the default runner model when `--model` is omitted
|
|
1772
|
+
* Environment variable used as the default runner model when `--model` is omitted or not set in `CliAgent`.
|
|
1766
1773
|
*
|
|
1767
|
-
* @
|
|
1774
|
+
* @public exported from `@promptbook/node`
|
|
1768
1775
|
*/
|
|
1769
1776
|
const PTBK_MODEL_ENV = 'PTBK_MODEL';
|
|
1770
1777
|
/**
|
|
1771
|
-
* Environment variable used as the default
|
|
1778
|
+
* Environment variable used as the default thinking level when `--thinking-level` is omitted or not set in `CliAgent`.
|
|
1772
1779
|
*
|
|
1773
|
-
* @
|
|
1780
|
+
* @public exported from `@promptbook/node`
|
|
1774
1781
|
*/
|
|
1775
1782
|
const PTBK_THINKING_LEVEL_ENV = 'PTBK_THINKING_LEVEL';
|
|
1783
|
+
|
|
1784
|
+
/**
|
|
1785
|
+
* Runner identifiers supported by Promptbook CLI agent orchestration commands.
|
|
1786
|
+
*
|
|
1787
|
+
* @private internal utility of `promptbookCli`
|
|
1788
|
+
*/
|
|
1789
|
+
const PROMPT_RUNNER_HARNESS_NAMES = CLI_AGENT_HARNESS_NAMES;
|
|
1776
1790
|
/**
|
|
1777
1791
|
* Description block shared by runner-backed CLI commands.
|
|
1778
1792
|
*
|
|
@@ -2056,42 +2070,44 @@
|
|
|
2056
2070
|
// Note: [🟡] Code for CLI command [agent](src/cli/cli-commands/agent.ts) should never be published outside of `@promptbook/cli`
|
|
2057
2071
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2058
2072
|
|
|
2073
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
2059
2074
|
/**
|
|
2060
|
-
* Relative path to the local agent source
|
|
2075
|
+
* Relative path to the local agent source used by the agent folder convention.
|
|
2061
2076
|
*
|
|
2062
|
-
* @
|
|
2077
|
+
* @public exported from `@promptbook/node`
|
|
2063
2078
|
*/
|
|
2064
2079
|
const AGENT_BOOK_FILE_PATH = 'agent.book';
|
|
2065
2080
|
/**
|
|
2066
|
-
* Relative path to
|
|
2081
|
+
* Relative path to the message queue root used by the agent folder convention.
|
|
2067
2082
|
*
|
|
2068
|
-
* @
|
|
2069
|
-
*/
|
|
2070
|
-
const AGENT_KNOWLEDGE_DIRECTORY_PATH = 'knowledge';
|
|
2071
|
-
/**
|
|
2072
|
-
* Relative path to the message queue root initialized by `ptbk agent-folder init`.
|
|
2073
|
-
*
|
|
2074
|
-
* @private internal utility of `ptbk agent-folder`
|
|
2083
|
+
* @public exported from `@promptbook/node`
|
|
2075
2084
|
*/
|
|
2076
2085
|
const AGENT_MESSAGES_DIRECTORY_PATH = 'messages';
|
|
2077
2086
|
/**
|
|
2078
|
-
* Relative path to queued user messages consumed by
|
|
2087
|
+
* Relative path to queued user messages consumed by the agent runner.
|
|
2079
2088
|
*
|
|
2080
|
-
* @
|
|
2089
|
+
* @public exported from `@promptbook/node`
|
|
2081
2090
|
*/
|
|
2082
2091
|
const AGENT_QUEUED_MESSAGES_DIRECTORY_PATH = path.join(AGENT_MESSAGES_DIRECTORY_PATH, 'queued');
|
|
2083
2092
|
/**
|
|
2084
|
-
* Relative path to answered messages written by
|
|
2093
|
+
* Relative path to answered messages written by the agent runner.
|
|
2085
2094
|
*
|
|
2086
|
-
* @
|
|
2095
|
+
* @public exported from `@promptbook/node`
|
|
2087
2096
|
*/
|
|
2088
2097
|
const AGENT_FINISHED_MESSAGES_DIRECTORY_PATH = path.join(AGENT_MESSAGES_DIRECTORY_PATH, 'finished');
|
|
2089
2098
|
/**
|
|
2090
2099
|
* Relative path to messages that the agent runner stopped retrying.
|
|
2091
2100
|
*
|
|
2092
|
-
* @
|
|
2101
|
+
* @public exported from `@promptbook/node`
|
|
2093
2102
|
*/
|
|
2094
2103
|
const AGENT_FAILED_MESSAGES_DIRECTORY_PATH = path.join(AGENT_MESSAGES_DIRECTORY_PATH, 'failed');
|
|
2104
|
+
|
|
2105
|
+
/**
|
|
2106
|
+
* Relative path to local knowledge files initialized by `ptbk agent-folder init`.
|
|
2107
|
+
*
|
|
2108
|
+
* @private internal utility of `ptbk agent-folder`
|
|
2109
|
+
*/
|
|
2110
|
+
const AGENT_KNOWLEDGE_DIRECTORY_PATH = 'knowledge';
|
|
2095
2111
|
/**
|
|
2096
2112
|
* Relative path to generated local agent documentation initialized by `ptbk agent-folder init`.
|
|
2097
2113
|
*
|
|
@@ -5124,6 +5140,7 @@
|
|
|
5124
5140
|
noUi: options.noUi,
|
|
5125
5141
|
thinkingLevel: options.thinkingLevel,
|
|
5126
5142
|
waitForUser: false,
|
|
5143
|
+
waitBetweenPrompts: 0,
|
|
5127
5144
|
noCommit: options.noCommit,
|
|
5128
5145
|
ignoreGitChanges: options.ignoreGitChanges,
|
|
5129
5146
|
normalizeLineEndings: options.normalizeLineEndings,
|
|
@@ -6111,7 +6128,7 @@
|
|
|
6111
6128
|
* @public exported from `@promptbook/utils`
|
|
6112
6129
|
*/
|
|
6113
6130
|
function computeHash(value) {
|
|
6114
|
-
return
|
|
6131
|
+
return CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(_spaceTrim.spaceTrim(valueToString(value)))).toString( /* hex */);
|
|
6115
6132
|
}
|
|
6116
6133
|
// TODO: [🥬][🥬] Use this ACRY
|
|
6117
6134
|
|
|
@@ -10816,21 +10833,22 @@
|
|
|
10816
10833
|
* @private helper of `fractalAvatarVisual`
|
|
10817
10834
|
*/
|
|
10818
10835
|
function drawDragonCurveLayer(context, points, options) {
|
|
10819
|
-
const {
|
|
10836
|
+
const { primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
|
|
10820
10837
|
const firstPoint = points[0];
|
|
10821
10838
|
const lastPoint = points[points.length - 1];
|
|
10822
10839
|
const ribbonGradient = context.createLinearGradient(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y);
|
|
10823
10840
|
ribbonGradient.addColorStop(0, `${primaryColor}f2`);
|
|
10824
10841
|
ribbonGradient.addColorStop(0.5, `${secondaryColor}e6`);
|
|
10825
10842
|
ribbonGradient.addColorStop(1, `${tertiaryColor}f2`);
|
|
10843
|
+
// Approximate the blurred shadow stroke with a wider semi-transparent stroke instead of
|
|
10844
|
+
// context.filter blur, which triggers a costly software rasterization pass every frame.
|
|
10826
10845
|
context.save();
|
|
10827
10846
|
context.beginPath();
|
|
10828
10847
|
tracePolyline(context, points);
|
|
10829
|
-
context.strokeStyle = `${shadowColor}
|
|
10830
|
-
context.lineWidth = strokeWidth *
|
|
10848
|
+
context.strokeStyle = `${shadowColor}48`;
|
|
10849
|
+
context.lineWidth = strokeWidth * 4.5;
|
|
10831
10850
|
context.lineJoin = 'round';
|
|
10832
10851
|
context.lineCap = 'round';
|
|
10833
|
-
context.filter = `blur(${size * 0.022}px)`;
|
|
10834
10852
|
context.stroke();
|
|
10835
10853
|
context.restore();
|
|
10836
10854
|
context.beginPath();
|
|
@@ -11414,11 +11432,23 @@
|
|
|
11414
11432
|
* @private helper of `minecraft2AvatarVisual`
|
|
11415
11433
|
*/
|
|
11416
11434
|
function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
|
|
11435
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.03;
|
|
11436
|
+
const cy = size * 0.85 + Math.sin(timeMs / 880) * size * 0.01;
|
|
11437
|
+
const rx = size * (0.16 + interaction.intensity * 0.015);
|
|
11438
|
+
const ry = size * 0.055;
|
|
11439
|
+
// Radial gradient approximates the blurry ellipse shadow without context.filter blur.
|
|
11417
11440
|
context.save();
|
|
11418
|
-
context.
|
|
11419
|
-
context.
|
|
11441
|
+
context.translate(cx, cy);
|
|
11442
|
+
context.scale(1, ry / rx);
|
|
11443
|
+
const blurRadius = rx * 1.4;
|
|
11444
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
11445
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
11446
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
11447
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
11448
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
11449
|
+
context.fillStyle = shadowGradient;
|
|
11420
11450
|
context.beginPath();
|
|
11421
|
-
context.
|
|
11451
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
11422
11452
|
context.fill();
|
|
11423
11453
|
context.restore();
|
|
11424
11454
|
}
|
|
@@ -11642,13 +11672,27 @@
|
|
|
11642
11672
|
spotlight.addColorStop(1, `${palette.highlight}00`);
|
|
11643
11673
|
context.fillStyle = spotlight;
|
|
11644
11674
|
context.fillRect(0, 0, size, size);
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11675
|
+
{
|
|
11676
|
+
// Radial gradient approximates the blurry ellipse shadow without context.filter blur.
|
|
11677
|
+
const cx = size * 0.5;
|
|
11678
|
+
const cy = size * 0.86;
|
|
11679
|
+
const rx = size * 0.2;
|
|
11680
|
+
const ry = size * 0.06;
|
|
11681
|
+
const blurRadius = rx * 1.4;
|
|
11682
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
11683
|
+
shadowGradient.addColorStop(0, 'rgba(0,0,0,0.28)');
|
|
11684
|
+
shadowGradient.addColorStop(0.45, 'rgba(0,0,0,0.14)');
|
|
11685
|
+
shadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.05)');
|
|
11686
|
+
shadowGradient.addColorStop(1, 'rgba(0,0,0,0)');
|
|
11687
|
+
context.save();
|
|
11688
|
+
context.translate(cx, cy);
|
|
11689
|
+
context.scale(1, ry / rx);
|
|
11690
|
+
context.fillStyle = shadowGradient;
|
|
11691
|
+
context.beginPath();
|
|
11692
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
11693
|
+
context.fill();
|
|
11694
|
+
context.restore();
|
|
11695
|
+
}
|
|
11652
11696
|
drawVoxelCuboid(context, {
|
|
11653
11697
|
x: bodyX,
|
|
11654
11698
|
y: bodyY,
|
|
@@ -12700,6 +12744,35 @@
|
|
|
12700
12744
|
y: -0.62,
|
|
12701
12745
|
z: 0.94,
|
|
12702
12746
|
});
|
|
12747
|
+
/**
|
|
12748
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
12749
|
+
*
|
|
12750
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
12751
|
+
*/
|
|
12752
|
+
const octopus3dStableStateCache = new WeakMap();
|
|
12753
|
+
/**
|
|
12754
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
12755
|
+
*
|
|
12756
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
12757
|
+
*/
|
|
12758
|
+
function getOctopus3dStableState(createRandom) {
|
|
12759
|
+
const cached = octopus3dStableStateCache.get(createRandom);
|
|
12760
|
+
if (cached !== undefined) {
|
|
12761
|
+
return cached;
|
|
12762
|
+
}
|
|
12763
|
+
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
12764
|
+
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
12765
|
+
const leftEyePhaseOffset = eyeRandom() * 0.6;
|
|
12766
|
+
const rightEyePhaseOffset = eyeRandom() * 0.6;
|
|
12767
|
+
const state = {
|
|
12768
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
12769
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
12770
|
+
leftEyePhaseOffset,
|
|
12771
|
+
rightEyePhaseOffset,
|
|
12772
|
+
};
|
|
12773
|
+
octopus3dStableStateCache.set(createRandom, state);
|
|
12774
|
+
return state;
|
|
12775
|
+
}
|
|
12703
12776
|
/**
|
|
12704
12777
|
* Proper 3D Octopus visual built from projected organic meshes and tentacles.
|
|
12705
12778
|
*
|
|
@@ -12712,10 +12785,7 @@
|
|
|
12712
12785
|
isAnimated: true,
|
|
12713
12786
|
supportsPointerTracking: true,
|
|
12714
12787
|
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;
|
|
12788
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
|
|
12719
12789
|
const sceneCenterX = size * 0.5;
|
|
12720
12790
|
const sceneCenterY = size * 0.56;
|
|
12721
12791
|
const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
|
|
@@ -12812,12 +12882,12 @@
|
|
|
12812
12882
|
x: -faceEyeSpacing,
|
|
12813
12883
|
y: faceEyeYOffset,
|
|
12814
12884
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
12815
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase +
|
|
12885
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
12816
12886
|
drawProjectedOrganicEye(context, {
|
|
12817
12887
|
x: faceEyeSpacing,
|
|
12818
12888
|
y: faceEyeYOffset,
|
|
12819
12889
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
12820
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 +
|
|
12890
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
12821
12891
|
drawProjectedOrganicMouth(context, [
|
|
12822
12892
|
{
|
|
12823
12893
|
x: -mouthHalfWidth,
|
|
@@ -12861,14 +12931,28 @@
|
|
|
12861
12931
|
/**
|
|
12862
12932
|
* Draws the soft ground shadow below the octopus.
|
|
12863
12933
|
*
|
|
12934
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
12935
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
12936
|
+
*
|
|
12864
12937
|
* @private helper of `octopus3dAvatarVisual`
|
|
12865
12938
|
*/
|
|
12866
12939
|
function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
|
|
12940
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.04;
|
|
12941
|
+
const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
|
|
12942
|
+
const rx = size * (0.18 + interaction.intensity * 0.02);
|
|
12943
|
+
const ry = size * 0.06;
|
|
12867
12944
|
context.save();
|
|
12868
|
-
context.
|
|
12869
|
-
context.
|
|
12945
|
+
context.translate(cx, cy);
|
|
12946
|
+
context.scale(1, ry / rx);
|
|
12947
|
+
const blurRadius = rx * 1.4;
|
|
12948
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
12949
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
12950
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
12951
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
12952
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
12953
|
+
context.fillStyle = shadowGradient;
|
|
12870
12954
|
context.beginPath();
|
|
12871
|
-
context.
|
|
12955
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
12872
12956
|
context.fill();
|
|
12873
12957
|
context.restore();
|
|
12874
12958
|
}
|
|
@@ -13099,6 +13183,35 @@
|
|
|
13099
13183
|
y: -0.6,
|
|
13100
13184
|
z: 0.98,
|
|
13101
13185
|
});
|
|
13186
|
+
/**
|
|
13187
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
13188
|
+
*
|
|
13189
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
13190
|
+
*/
|
|
13191
|
+
const octopus3d2StableStateCache = new WeakMap();
|
|
13192
|
+
/**
|
|
13193
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
13194
|
+
*
|
|
13195
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
13196
|
+
*/
|
|
13197
|
+
function getOctopus3d2StableState(createRandom) {
|
|
13198
|
+
const cached = octopus3d2StableStateCache.get(createRandom);
|
|
13199
|
+
if (cached !== undefined) {
|
|
13200
|
+
return cached;
|
|
13201
|
+
}
|
|
13202
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
13203
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
13204
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
13205
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
13206
|
+
const state = {
|
|
13207
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
13208
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
13209
|
+
leftEyePhaseOffset,
|
|
13210
|
+
rightEyePhaseOffset,
|
|
13211
|
+
};
|
|
13212
|
+
octopus3d2StableStateCache.set(createRandom, state);
|
|
13213
|
+
return state;
|
|
13214
|
+
}
|
|
13102
13215
|
/**
|
|
13103
13216
|
* Octopus 3D 2 avatar visual.
|
|
13104
13217
|
*
|
|
@@ -13111,10 +13224,7 @@
|
|
|
13111
13224
|
isAnimated: true,
|
|
13112
13225
|
supportsPointerTracking: true,
|
|
13113
13226
|
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;
|
|
13227
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3d2StableState(createRandom);
|
|
13118
13228
|
const sceneCenterX = size * 0.5;
|
|
13119
13229
|
const sceneCenterY = size * 0.575;
|
|
13120
13230
|
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
@@ -13167,8 +13277,8 @@
|
|
|
13167
13277
|
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
13168
13278
|
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
13169
13279
|
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 +
|
|
13280
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
13281
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
13172
13282
|
drawProjectedOrganicMouth(context, [
|
|
13173
13283
|
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
13174
13284
|
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
@@ -13197,14 +13307,28 @@
|
|
|
13197
13307
|
/**
|
|
13198
13308
|
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
13199
13309
|
*
|
|
13310
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
13311
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
13312
|
+
*
|
|
13200
13313
|
* @private helper of `octopus3d2AvatarVisual`
|
|
13201
13314
|
*/
|
|
13202
13315
|
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
13316
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
13317
|
+
const cy = size * 0.88 + Math.sin(timeMs / 940) * size * 0.008;
|
|
13318
|
+
const rx = size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018);
|
|
13319
|
+
const ry = size * 0.062;
|
|
13203
13320
|
context.save();
|
|
13204
|
-
context.
|
|
13205
|
-
context.
|
|
13321
|
+
context.translate(cx, cy);
|
|
13322
|
+
context.scale(1, ry / rx);
|
|
13323
|
+
const blurRadius = rx * 1.4;
|
|
13324
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
13325
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
13326
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
13327
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
13328
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
13329
|
+
context.fillStyle = shadowGradient;
|
|
13206
13330
|
context.beginPath();
|
|
13207
|
-
context.
|
|
13331
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
13208
13332
|
context.fill();
|
|
13209
13333
|
context.restore();
|
|
13210
13334
|
}
|
|
@@ -13360,6 +13484,40 @@
|
|
|
13360
13484
|
* @private helper of `octopus3d3AvatarVisual`
|
|
13361
13485
|
*/
|
|
13362
13486
|
const OCTOPUS_TENTACLE_COUNT = 8;
|
|
13487
|
+
/**
|
|
13488
|
+
* Cache keyed by the `createRandom` factory reference, which is stable for the lifetime of one
|
|
13489
|
+
* mounted `<Avatar/>` component (created inside `resolveAvatarRenderDefinition` and held in a
|
|
13490
|
+
* React `useMemo`). Using a `WeakMap` ensures the entry is collected when the component unmounts.
|
|
13491
|
+
*
|
|
13492
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13493
|
+
*/
|
|
13494
|
+
const stableStateCache = new WeakMap();
|
|
13495
|
+
/**
|
|
13496
|
+
* Returns the stable per-avatar state, computing it on first access and returning the cached
|
|
13497
|
+
* result on every subsequent call within the same `<Avatar/>` mount.
|
|
13498
|
+
*
|
|
13499
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
13500
|
+
*/
|
|
13501
|
+
function getOctopus3d3StableState(createRandom) {
|
|
13502
|
+
const cached = stableStateCache.get(createRandom);
|
|
13503
|
+
if (cached !== undefined) {
|
|
13504
|
+
return cached;
|
|
13505
|
+
}
|
|
13506
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
13507
|
+
const animationRandom = createRandom('octopus3d3-animation-profile');
|
|
13508
|
+
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
13509
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
13510
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
13511
|
+
const state = {
|
|
13512
|
+
morphologyProfile,
|
|
13513
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
13514
|
+
leftEyePhaseOffset,
|
|
13515
|
+
rightEyePhaseOffset,
|
|
13516
|
+
tentacleProfiles: createContinuousTentacleProfiles(createRandom, morphologyProfile),
|
|
13517
|
+
};
|
|
13518
|
+
stableStateCache.set(createRandom, state);
|
|
13519
|
+
return state;
|
|
13520
|
+
}
|
|
13363
13521
|
/**
|
|
13364
13522
|
* Octopus 3D 3 avatar visual.
|
|
13365
13523
|
*
|
|
@@ -13372,11 +13530,7 @@
|
|
|
13372
13530
|
isAnimated: true,
|
|
13373
13531
|
supportsPointerTracking: true,
|
|
13374
13532
|
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);
|
|
13533
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles } = getOctopus3d3StableState(createRandom);
|
|
13380
13534
|
const sceneCenterX = size * 0.5;
|
|
13381
13535
|
const sceneCenterY = size * 0.535;
|
|
13382
13536
|
const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
|
|
@@ -13453,8 +13607,8 @@
|
|
|
13453
13607
|
size,
|
|
13454
13608
|
palette,
|
|
13455
13609
|
});
|
|
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 +
|
|
13610
|
+
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
13611
|
+
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
13612
|
drawProjectedOrganicMouth(context, [
|
|
13459
13613
|
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
13460
13614
|
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
@@ -13505,14 +13659,30 @@
|
|
|
13505
13659
|
/**
|
|
13506
13660
|
* Draws the soft lower shadow that anchors the octopus in the avatar frame.
|
|
13507
13661
|
*
|
|
13662
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
13663
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
13664
|
+
*
|
|
13508
13665
|
* @private helper of `octopus3d3AvatarVisual`
|
|
13509
13666
|
*/
|
|
13510
13667
|
function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
13668
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
13669
|
+
const cy = size * 0.9 + Math.sin(timeMs / 980) * size * 0.007;
|
|
13670
|
+
const rx = size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02);
|
|
13671
|
+
const ry = size * 0.06;
|
|
13672
|
+
// Scale the context so that drawing a circle produces the correct ellipse aspect ratio,
|
|
13673
|
+
// then fill with a radial gradient that approximates the blurry edge without context.filter.
|
|
13511
13674
|
context.save();
|
|
13512
|
-
context.
|
|
13513
|
-
context.
|
|
13675
|
+
context.translate(cx, cy);
|
|
13676
|
+
context.scale(1, ry / rx);
|
|
13677
|
+
const blurRadius = rx * 1.4;
|
|
13678
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
13679
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
13680
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
13681
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
13682
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
13683
|
+
context.fillStyle = shadowGradient;
|
|
13514
13684
|
context.beginPath();
|
|
13515
|
-
context.
|
|
13685
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
13516
13686
|
context.fill();
|
|
13517
13687
|
context.restore();
|
|
13518
13688
|
}
|
|
@@ -22117,7 +22287,7 @@
|
|
|
22117
22287
|
* @private internal helper function
|
|
22118
22288
|
*/
|
|
22119
22289
|
function $randomToken(randomness) {
|
|
22120
|
-
return
|
|
22290
|
+
return CryptoJS__default["default"].lib.WordArray.random(randomness).toString(CryptoJS__default["default"].enc.Hex);
|
|
22121
22291
|
}
|
|
22122
22292
|
// TODO: [🤶] Maybe export through `@promptbook/utils` or `@promptbook/random` package
|
|
22123
22293
|
// TODO: Maybe use nanoid instead https://github.com/ai/nanoid
|
|
@@ -28421,7 +28591,7 @@
|
|
|
28421
28591
|
askForApproval: 'never',
|
|
28422
28592
|
allowCredits: options.allowCredits,
|
|
28423
28593
|
});
|
|
28424
|
-
if (!options.allowCredits) {
|
|
28594
|
+
if (!options.allowCredits && options.isVerbose === true) {
|
|
28425
28595
|
console.info(colors__default["default"].gray('OpenAI Codex credit spending is disabled. Use `--allow-credits` to explicitly opt in.'));
|
|
28426
28596
|
}
|
|
28427
28597
|
return createRunnerResolution(options, runner, actualRunnerModel);
|
|
@@ -28737,14 +28907,50 @@
|
|
|
28737
28907
|
* Builds the prompt sent to the selected coding runner for one queued user-thread book.
|
|
28738
28908
|
*/
|
|
28739
28909
|
function buildAgentMessagePrompt(messageRelativePath, agentSystemMessage) {
|
|
28740
|
-
|
|
28741
|
-
|
|
28910
|
+
return _spaceTrim.spaceTrim((block) => `
|
|
28911
|
+
# Answer 1 user question
|
|
28742
28912
|
|
|
28743
|
-
|
|
28744
|
-
|
|
28745
|
-
|
|
28746
|
-
|
|
28747
|
-
|
|
28913
|
+
- Read \`${messageRelativePath}\` and answer the most recent \`MESSAGE @User\`
|
|
28914
|
+
- Only change the queued message file by appending one new \`MESSAGE @Agent\` block
|
|
28915
|
+
- Do not modify any other file in the repository
|
|
28916
|
+
|
|
28917
|
+
## Rules for the answering
|
|
28918
|
+
|
|
28919
|
+
## Formatting
|
|
28920
|
+
|
|
28921
|
+
- You can use Markdown formatting in the messages like **bold** or *italic*
|
|
28922
|
+
|
|
28923
|
+
## Sources and citations
|
|
28924
|
+
|
|
28925
|
+
Mark sources and citations like this "【https://example.com/document123.pdf 】"
|
|
28926
|
+
|
|
28927
|
+
At the same time, you can write sources naturally in the text of the answers
|
|
28928
|
+
|
|
28929
|
+
For example:
|
|
28930
|
+
|
|
28931
|
+
> According to paragraph §745b, the fee can be waived for a person over 65 years old. 【https://praha13.cz/2026/paragraph-745.doc】
|
|
28932
|
+
|
|
28933
|
+
- "paragraph §745b" fits naturally in the text.
|
|
28934
|
+
- "【https://praha13.cz/2026/paragraph-745.doc】" The exact format of the quote is important for further processing of the answer.
|
|
28935
|
+
- 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.
|
|
28936
|
+
|
|
28937
|
+
## Quick buttons
|
|
28938
|
+
|
|
28939
|
+
If there is a meaningful follow-up procedure, use quick buttons at the end of the answer:
|
|
28940
|
+
|
|
28941
|
+
\`\`\`
|
|
28942
|
+
How big is the contract you are posting?
|
|
28943
|
+
|
|
28944
|
+
[Up to 50,000 CZK](?message=We are posting an order up to 50,000 CZK)
|
|
28945
|
+
[Up to 100,000 CZK](?message=We are posting an order up to 100,000 CZK)
|
|
28946
|
+
[Over 100,000 CZK](?message=We are posting an order over 100,000 CZK)
|
|
28947
|
+
\`\`\`
|
|
28948
|
+
|
|
28949
|
+
|
|
28950
|
+
## This is how you should behave
|
|
28951
|
+
|
|
28952
|
+
${block(agentSystemMessage)}
|
|
28953
|
+
`);
|
|
28748
28954
|
}
|
|
28749
28955
|
|
|
28750
28956
|
/**
|
|
@@ -31358,7 +31564,7 @@
|
|
|
31358
31564
|
* @public exported from `@promptbook/editable`
|
|
31359
31565
|
*/
|
|
31360
31566
|
function knowledgeSourceContentToName(knowledgeSourceContent) {
|
|
31361
|
-
const hash =
|
|
31567
|
+
const hash = CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(JSON.stringify(knowledgeSourceContent)))
|
|
31362
31568
|
// <- TODO: [🥬] Encapsulate sha256 to some private utility function
|
|
31363
31569
|
.toString( /* hex */)
|
|
31364
31570
|
.substring(0, 20);
|
|
@@ -32206,7 +32412,7 @@
|
|
|
32206
32412
|
console.warn('CSV string contains carriage return characters, but in the CSV settings the `newline` setting does not include them. Autohealing the CSV string.');
|
|
32207
32413
|
value = value.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
32208
32414
|
}
|
|
32209
|
-
const csv =
|
|
32415
|
+
const csv = papaparse__default["default"].parse(value, settings);
|
|
32210
32416
|
return csv;
|
|
32211
32417
|
}
|
|
32212
32418
|
|
|
@@ -32291,10 +32497,10 @@
|
|
|
32291
32497
|
i > index ? { ...row, [outputParameterName]: PENDING_VALUE_PLACEHOLDER } : row,
|
|
32292
32498
|
);
|
|
32293
32499
|
*/
|
|
32294
|
-
await onProgress(
|
|
32500
|
+
await onProgress(papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS }));
|
|
32295
32501
|
}
|
|
32296
32502
|
}
|
|
32297
|
-
return
|
|
32503
|
+
return papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
32298
32504
|
},
|
|
32299
32505
|
},
|
|
32300
32506
|
{
|
|
@@ -32322,7 +32528,7 @@
|
|
|
32322
32528
|
return /* not await */ mapCallback({ [key]: value }, index, array.length);
|
|
32323
32529
|
}));
|
|
32324
32530
|
}));
|
|
32325
|
-
return
|
|
32531
|
+
return papaparse__default["default"].unparse(mappedData, { ...settings, ...MANDATORY_CSV_SETTINGS });
|
|
32326
32532
|
},
|
|
32327
32533
|
},
|
|
32328
32534
|
],
|
|
@@ -35889,7 +36095,9 @@
|
|
|
35889
36095
|
* @private internal utility of `Book`
|
|
35890
36096
|
*/
|
|
35891
36097
|
function parseCommitmentHeader(line) {
|
|
35892
|
-
|
|
36098
|
+
// Require at least 2 characters in the first keyword word to avoid treating common
|
|
36099
|
+
// single-letter words (e.g. "V" in Czech, "I" or "A" in English) as commitment headers.
|
|
36100
|
+
const match = /^([A-Z][A-Z0-9]+(?: [A-Z0-9]+)*)(?:\s+(.*))?$/u.exec(line);
|
|
35893
36101
|
if (!match) {
|
|
35894
36102
|
return null;
|
|
35895
36103
|
}
|
|
@@ -39303,6 +39511,57 @@
|
|
|
39303
39511
|
// Note: [🟡] Code for CLI command [init](src/cli/cli-commands/coder/init.ts) should never be published outside of `@promptbook/cli`
|
|
39304
39512
|
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
39305
39513
|
|
|
39514
|
+
/**
|
|
39515
|
+
* Pattern that matches durations like "1h", "30m", "5s", "1h30m", "1h30m5s".
|
|
39516
|
+
*/
|
|
39517
|
+
const DURATION_PATTERN = /^(?:(\d+)h)?(?:(\d+)m(?:in)?)?(?:(\d+)s)?$/;
|
|
39518
|
+
/**
|
|
39519
|
+
* Parses a human-readable duration string into milliseconds.
|
|
39520
|
+
*
|
|
39521
|
+
* Supported formats: `Xh`, `Xm`, `Xs`, and combinations like `1h30m`, `1h30m5s`.
|
|
39522
|
+
*
|
|
39523
|
+
* @returns Duration in milliseconds
|
|
39524
|
+
* @throws When the string does not match any supported format
|
|
39525
|
+
*
|
|
39526
|
+
* @private internal utility of `ptbk coder run`
|
|
39527
|
+
*/
|
|
39528
|
+
function parseDuration(durationString) {
|
|
39529
|
+
var _a, _b, _c;
|
|
39530
|
+
const trimmed = durationString.trim();
|
|
39531
|
+
if (!trimmed) {
|
|
39532
|
+
throw new Error(`Invalid duration: empty string. Expected a format like "1h", "30m", "5s", or combinations like "1h30m".`);
|
|
39533
|
+
}
|
|
39534
|
+
const match = trimmed.match(DURATION_PATTERN);
|
|
39535
|
+
if (!match || (match[1] === undefined && match[2] === undefined && match[3] === undefined)) {
|
|
39536
|
+
throw new Error(`Invalid duration: "${durationString}". Expected a format like "1h", "30m", "5s", or combinations like "1h30m5s".`);
|
|
39537
|
+
}
|
|
39538
|
+
const hours = parseInt((_a = match[1]) !== null && _a !== void 0 ? _a : '0', 10);
|
|
39539
|
+
const minutes = parseInt((_b = match[2]) !== null && _b !== void 0 ? _b : '0', 10);
|
|
39540
|
+
const seconds = parseInt((_c = match[3]) !== null && _c !== void 0 ? _c : '0', 10);
|
|
39541
|
+
return (hours * 3600 + minutes * 60 + seconds) * 1000;
|
|
39542
|
+
}
|
|
39543
|
+
/**
|
|
39544
|
+
* Formats a duration in milliseconds into a compact human-readable string.
|
|
39545
|
+
*
|
|
39546
|
+
* Examples: `3600000` → `"1h"`, `90000` → `"1m 30s"`, `5000` → `"5s"`.
|
|
39547
|
+
*
|
|
39548
|
+
* @private internal utility of `ptbk coder run`
|
|
39549
|
+
*/
|
|
39550
|
+
function formatDurationMs(ms) {
|
|
39551
|
+
const totalSeconds = Math.ceil(ms / 1000);
|
|
39552
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
39553
|
+
const minutes = Math.floor((totalSeconds % 3600) / 60);
|
|
39554
|
+
const seconds = totalSeconds % 60;
|
|
39555
|
+
const parts = [];
|
|
39556
|
+
if (hours > 0)
|
|
39557
|
+
parts.push(`${hours}h`);
|
|
39558
|
+
if (minutes > 0)
|
|
39559
|
+
parts.push(`${minutes}m`);
|
|
39560
|
+
if (seconds > 0 || parts.length === 0)
|
|
39561
|
+
parts.push(`${seconds}s`);
|
|
39562
|
+
return parts.join(' ');
|
|
39563
|
+
}
|
|
39564
|
+
|
|
39306
39565
|
/**
|
|
39307
39566
|
* Initializes `coder run` command for Promptbook CLI utilities
|
|
39308
39567
|
*
|
|
@@ -39335,7 +39594,13 @@
|
|
|
39335
39594
|
command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
|
|
39336
39595
|
addPromptRunnerExecutionOptions(command);
|
|
39337
39596
|
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
|
|
39338
|
-
command.option('--
|
|
39597
|
+
command.option('--wait [duration]', _spaceTrim.spaceTrim(`
|
|
39598
|
+
Wait between prompt rounds.
|
|
39599
|
+
Without a value (default): waits for user confirmation before each prompt (interactive mode).
|
|
39600
|
+
With a duration like 1h, 30m, 5s: waits that long between prompts to avoid hitting rate limits of the harness.
|
|
39601
|
+
`), true);
|
|
39602
|
+
// Note: --no-wait disables the default interactive wait-for-user behaviour
|
|
39603
|
+
command.option('--no-wait', 'Skip all waiting between prompts and run non-interactively');
|
|
39339
39604
|
command.option('--auto-migrate', 'Run testing-server database migrations automatically after each successfully processed prompt');
|
|
39340
39605
|
command.option('--allow-destructive-auto-migrate', 'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations');
|
|
39341
39606
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
@@ -39344,10 +39609,23 @@
|
|
|
39344
39609
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions, {
|
|
39345
39610
|
isAgentRequired: !dryRun,
|
|
39346
39611
|
});
|
|
39612
|
+
// [1] Parse the --wait option:
|
|
39613
|
+
// true (default or --wait without value): wait for user confirmation
|
|
39614
|
+
// false (--no-wait): no waiting at all
|
|
39615
|
+
// string (--wait 1h): wait that long between prompt rounds
|
|
39616
|
+
let waitForUser = false;
|
|
39617
|
+
let waitBetweenPrompts = 0;
|
|
39618
|
+
if (wait === true) {
|
|
39619
|
+
waitForUser = true;
|
|
39620
|
+
}
|
|
39621
|
+
else if (typeof wait === 'string' && wait !== '') {
|
|
39622
|
+
waitBetweenPrompts = parseDuration(wait);
|
|
39623
|
+
}
|
|
39347
39624
|
// Convert commander options to RunOptions format
|
|
39348
39625
|
const runOptions = {
|
|
39349
39626
|
dryRun,
|
|
39350
|
-
waitForUser
|
|
39627
|
+
waitForUser,
|
|
39628
|
+
waitBetweenPrompts,
|
|
39351
39629
|
noCommit: runnerOptions.noCommit,
|
|
39352
39630
|
ignoreGitChanges: runnerOptions.ignoreGitChanges,
|
|
39353
39631
|
agentName: runnerOptions.agentName,
|
|
@@ -45338,7 +45616,7 @@
|
|
|
45338
45616
|
const { filename: sourceFilename, url } = source;
|
|
45339
45617
|
const { rootDirname, cacheDirname, intermediateFilesStrategy, extension, isVerbose } = options;
|
|
45340
45618
|
// TODO: [👬] DRY
|
|
45341
|
-
const hash =
|
|
45619
|
+
const hash = CryptoJS__default["default"].SHA256(
|
|
45342
45620
|
// <- TODO: [🥬] Encapsulate sha256 to some private utility function
|
|
45343
45621
|
hexEncoder__default["default"].parse(sourceFilename || url || 'untitled'))
|
|
45344
45622
|
.toString( /* hex */)
|
|
@@ -45429,7 +45707,7 @@
|
|
|
45429
45707
|
* @private utility of `WebsiteScraper`
|
|
45430
45708
|
*/
|
|
45431
45709
|
function createShowdownConverter() {
|
|
45432
|
-
return new
|
|
45710
|
+
return new showdown__default["default"].Converter({
|
|
45433
45711
|
flavor: 'github',
|
|
45434
45712
|
/*
|
|
45435
45713
|
> import showdownHighlight from 'showdown-highlight';
|
|
@@ -62790,10 +63068,12 @@
|
|
|
62790
63068
|
noUi: options.noUi,
|
|
62791
63069
|
thinkingLevel: options.thinkingLevel,
|
|
62792
63070
|
waitForUser: false,
|
|
63071
|
+
waitBetweenPrompts: 0,
|
|
62793
63072
|
noCommit: true,
|
|
62794
63073
|
ignoreGitChanges: true,
|
|
62795
63074
|
normalizeLineEndings: false,
|
|
62796
63075
|
allowCredits: options.allowCredits,
|
|
63076
|
+
isVerbose: options.isVerbose,
|
|
62797
63077
|
autoMigrate: false,
|
|
62798
63078
|
allowDestructiveAutoMigrate: false,
|
|
62799
63079
|
autoPush: false,
|
|
@@ -64826,7 +65106,7 @@
|
|
|
64826
65106
|
* Computes one stable hash from a JSON-serializable value.
|
|
64827
65107
|
*/
|
|
64828
65108
|
function computeJsonHash$1(value) {
|
|
64829
|
-
return
|
|
65109
|
+
return CryptoJS__default["default"].SHA256(JSON.stringify(value)).toString();
|
|
64830
65110
|
}
|
|
64831
65111
|
/**
|
|
64832
65112
|
* Handles OpenAI AgentKit-backed executions for `AgentLlmExecutionTools`.
|
|
@@ -64984,7 +65264,7 @@
|
|
|
64984
65264
|
* Computes one stable hash from a JSON-serializable value.
|
|
64985
65265
|
*/
|
|
64986
65266
|
function computeJsonHash(value) {
|
|
64987
|
-
return
|
|
65267
|
+
return CryptoJS__default["default"].SHA256(JSON.stringify(value)).toString();
|
|
64988
65268
|
}
|
|
64989
65269
|
/**
|
|
64990
65270
|
* Removes assistant-managed requirements before the prompt is executed via OpenAI Assistants.
|
|
@@ -65786,7 +66066,7 @@
|
|
|
65786
66066
|
* Returns a virtual model name representing the agent behavior.
|
|
65787
66067
|
*/
|
|
65788
66068
|
get modelName() {
|
|
65789
|
-
const hash =
|
|
66069
|
+
const hash = CryptoJS__default["default"].SHA256(hexEncoder__default["default"].parse(this.options.agentSource)).toString( /* hex */);
|
|
65790
66070
|
const agentId = hash.substring(0, 10);
|
|
65791
66071
|
return (normalizeToKebabCase(this.title) + '-' + agentId);
|
|
65792
66072
|
}
|
|
@@ -68323,7 +68603,7 @@
|
|
|
68323
68603
|
/**
|
|
68324
68604
|
* CLI usage text for this script.
|
|
68325
68605
|
*/
|
|
68326
|
-
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]';
|
|
68606
|
+
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]';
|
|
68327
68607
|
/**
|
|
68328
68608
|
* Top-level flags supported by this command.
|
|
68329
68609
|
*/
|
|
@@ -68340,6 +68620,7 @@
|
|
|
68340
68620
|
'--allow-credits',
|
|
68341
68621
|
'--auto-migrate',
|
|
68342
68622
|
'--allow-destructive-auto-migrate',
|
|
68623
|
+
'--wait',
|
|
68343
68624
|
'--no-wait',
|
|
68344
68625
|
'--no-commit',
|
|
68345
68626
|
'--ignore-git-changes',
|
|
@@ -68378,6 +68659,22 @@
|
|
|
68378
68659
|
const allowDestructiveAutoMigrate = args.includes('--allow-destructive-auto-migrate');
|
|
68379
68660
|
const autoPush = args.includes('--auto-push');
|
|
68380
68661
|
const autoPull = args.includes('--auto-pull');
|
|
68662
|
+
// [1] Parse --wait [duration]:
|
|
68663
|
+
// absent or --no-wait: no waiting
|
|
68664
|
+
// --wait (no value): wait for user confirmation
|
|
68665
|
+
// --wait 1h: wait 1h between prompt rounds to avoid rate limits
|
|
68666
|
+
const waitOptionalValue = readOptionalOptionValue(args, '--wait');
|
|
68667
|
+
let waitForUser = false;
|
|
68668
|
+
let waitBetweenPrompts = 0;
|
|
68669
|
+
if (waitOptionalValue === null) {
|
|
68670
|
+
// --wait present without a duration value: interactive mode
|
|
68671
|
+
waitForUser = true;
|
|
68672
|
+
}
|
|
68673
|
+
else if (waitOptionalValue !== undefined) {
|
|
68674
|
+
// --wait <duration>: time-based wait between rounds
|
|
68675
|
+
waitBetweenPrompts = parseDuration(waitOptionalValue);
|
|
68676
|
+
}
|
|
68677
|
+
// --no-wait (or no flag): both waitForUser and waitBetweenPrompts remain false/0
|
|
68381
68678
|
let thinkingLevel;
|
|
68382
68679
|
if (hasTestCommandFlag && testCommand === undefined) {
|
|
68383
68680
|
exitWithUsageError('Missing value for --test. Use a shell command such as `npm run test` and quote it when it contains top-level CLI flags.');
|
|
@@ -68396,7 +68693,8 @@
|
|
|
68396
68693
|
}
|
|
68397
68694
|
return {
|
|
68398
68695
|
dryRun,
|
|
68399
|
-
waitForUser
|
|
68696
|
+
waitForUser,
|
|
68697
|
+
waitBetweenPrompts,
|
|
68400
68698
|
noCommit,
|
|
68401
68699
|
ignoreGitChanges,
|
|
68402
68700
|
normalizeLineEndings,
|
|
@@ -68415,6 +68713,23 @@
|
|
|
68415
68713
|
priority,
|
|
68416
68714
|
};
|
|
68417
68715
|
}
|
|
68716
|
+
/**
|
|
68717
|
+
* Reads an optional value for a flag that may appear with or without a following value.
|
|
68718
|
+
*
|
|
68719
|
+
* Returns `undefined` when the flag is absent, `null` when the flag is present but has no value
|
|
68720
|
+
* (the next token is another flag or the end of args), and the value string otherwise.
|
|
68721
|
+
*/
|
|
68722
|
+
function readOptionalOptionValue(args, flag) {
|
|
68723
|
+
if (!args.includes(flag)) {
|
|
68724
|
+
return undefined;
|
|
68725
|
+
}
|
|
68726
|
+
const index = args.indexOf(flag);
|
|
68727
|
+
const nextArg = args[index + 1];
|
|
68728
|
+
if (nextArg === undefined || nextArg.startsWith('-')) {
|
|
68729
|
+
return null;
|
|
68730
|
+
}
|
|
68731
|
+
return nextArg;
|
|
68732
|
+
}
|
|
68418
68733
|
/**
|
|
68419
68734
|
* Reads a value of a CLI option that follows a given flag.
|
|
68420
68735
|
*/
|
|
@@ -70870,6 +71185,7 @@
|
|
|
70870
71185
|
initializeRunUi(uiHandle, runner.name, actualRunnerModel, options);
|
|
70871
71186
|
let hasShownUpcomingTasks = false;
|
|
70872
71187
|
let hasWaitedForStart = false;
|
|
71188
|
+
let hasRunAtLeastOneRound = false;
|
|
70873
71189
|
while (just(true)) {
|
|
70874
71190
|
if (options.autoPull && !options.dryRun) {
|
|
70875
71191
|
await waitForRequestedPause({
|
|
@@ -70905,6 +71221,16 @@
|
|
|
70905
71221
|
}
|
|
70906
71222
|
const nextPrompt = promptQueueSnapshot.nextPrompt;
|
|
70907
71223
|
const promptLabel = buildPromptLabelForDisplay(nextPrompt.file, nextPrompt.section);
|
|
71224
|
+
// Wait between prompt rounds (skipped for the first round)
|
|
71225
|
+
if (hasRunAtLeastOneRound) {
|
|
71226
|
+
await waitBetweenPromptRoundsIfNeeded({
|
|
71227
|
+
options,
|
|
71228
|
+
isRichUiEnabled,
|
|
71229
|
+
progressDisplay,
|
|
71230
|
+
uiHandle,
|
|
71231
|
+
});
|
|
71232
|
+
}
|
|
71233
|
+
hasRunAtLeastOneRound = true;
|
|
70908
71234
|
hasWaitedForStart = await waitForPromptConfirmationIfNeeded({
|
|
70909
71235
|
options,
|
|
70910
71236
|
nextPrompt,
|
|
@@ -71140,6 +71466,39 @@
|
|
|
71140
71466
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
71141
71467
|
return true;
|
|
71142
71468
|
}
|
|
71469
|
+
/**
|
|
71470
|
+
* Countdown update interval for the between-rounds wait display.
|
|
71471
|
+
*/
|
|
71472
|
+
const WAIT_COUNTDOWN_UPDATE_INTERVAL_MS = 30000;
|
|
71473
|
+
/**
|
|
71474
|
+
* Waits the configured time between prompt rounds to avoid hitting harness rate limits.
|
|
71475
|
+
* Does nothing when `waitBetweenPrompts` is zero.
|
|
71476
|
+
*/
|
|
71477
|
+
async function waitBetweenPromptRoundsIfNeeded(options) {
|
|
71478
|
+
const { options: runOptions, isRichUiEnabled, progressDisplay, uiHandle } = options;
|
|
71479
|
+
const { waitBetweenPrompts } = runOptions;
|
|
71480
|
+
if (waitBetweenPrompts <= 0) {
|
|
71481
|
+
return;
|
|
71482
|
+
}
|
|
71483
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.pauseTimer();
|
|
71484
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.pauseTimer();
|
|
71485
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('waiting');
|
|
71486
|
+
let remaining = waitBetweenPrompts;
|
|
71487
|
+
while (remaining > 0) {
|
|
71488
|
+
const statusMessage = `Waiting ${formatDurationMs(remaining)} before next prompt to avoid rate limits...`;
|
|
71489
|
+
if (!isRichUiEnabled) {
|
|
71490
|
+
console.info(colors__default["default"].gray(statusMessage));
|
|
71491
|
+
}
|
|
71492
|
+
else {
|
|
71493
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(statusMessage);
|
|
71494
|
+
}
|
|
71495
|
+
const sleepMs = Math.min(WAIT_COUNTDOWN_UPDATE_INTERVAL_MS, remaining);
|
|
71496
|
+
await new Promise((resolve) => setTimeout(resolve, sleepMs));
|
|
71497
|
+
remaining -= sleepMs;
|
|
71498
|
+
}
|
|
71499
|
+
progressDisplay === null || progressDisplay === void 0 ? void 0 : progressDisplay.resumeTimer();
|
|
71500
|
+
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.resumeTimer();
|
|
71501
|
+
}
|
|
71143
71502
|
/**
|
|
71144
71503
|
* Stops active displays and prints the git identity tip for real runs.
|
|
71145
71504
|
*/
|