@promptbook/browser 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/esm/index.es.js +197 -44
- package/esm/index.es.js.map +1 -1
- 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 +2 -2
- package/umd/index.umd.js +197 -44
- package/umd/index.umd.js.map +1 -1
- 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
|
@@ -11,6 +11,11 @@ import type { CliAgentThinkingLevel } from '../book-3.0/CliAgent';
|
|
|
11
11
|
import type { CliAgentRunOptions } from '../book-3.0/CliAgent';
|
|
12
12
|
import type { CliAgentOptions } from '../book-3.0/CliAgent';
|
|
13
13
|
import { CliAgent } from '../book-3.0/CliAgent';
|
|
14
|
+
import { CLI_AGENT_HARNESS_NAMES } from '../book-3.0/cliAgentEnv';
|
|
15
|
+
import { CLI_AGENT_THINKING_LEVEL_VALUES } from '../book-3.0/cliAgentEnv';
|
|
16
|
+
import { PTBK_HARNESS_ENV } from '../book-3.0/cliAgentEnv';
|
|
17
|
+
import { PTBK_MODEL_ENV } from '../book-3.0/cliAgentEnv';
|
|
18
|
+
import { PTBK_THINKING_LEVEL_ENV } from '../book-3.0/cliAgentEnv';
|
|
14
19
|
import type { LiteAgentOptions } from '../book-3.0/LiteAgent';
|
|
15
20
|
import type { LiteAgentRunOptions } from '../book-3.0/LiteAgent';
|
|
16
21
|
import { LiteAgent } from '../book-3.0/LiteAgent';
|
|
@@ -39,6 +44,11 @@ export type { CliAgentThinkingLevel };
|
|
|
39
44
|
export type { CliAgentRunOptions };
|
|
40
45
|
export type { CliAgentOptions };
|
|
41
46
|
export { CliAgent };
|
|
47
|
+
export { CLI_AGENT_HARNESS_NAMES };
|
|
48
|
+
export { CLI_AGENT_THINKING_LEVEL_VALUES };
|
|
49
|
+
export { PTBK_HARNESS_ENV };
|
|
50
|
+
export { PTBK_MODEL_ENV };
|
|
51
|
+
export { PTBK_THINKING_LEVEL_ENV };
|
|
42
52
|
export type { LiteAgentOptions };
|
|
43
53
|
export type { LiteAgentRunOptions };
|
|
44
54
|
export { LiteAgent };
|
|
@@ -15,7 +15,7 @@ export type BookNodeAgentSource = Book | string_book;
|
|
|
15
15
|
*/
|
|
16
16
|
export type BookNodeAgentSourceOptions = {
|
|
17
17
|
readonly agentPath?: string;
|
|
18
|
-
readonly book?: BookNodeAgentSource;
|
|
18
|
+
readonly book?: string | BookNodeAgentSource;
|
|
19
19
|
readonly currentWorkingDirectory?: string;
|
|
20
20
|
};
|
|
21
21
|
/**
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import type { BookNodeAgentSourceOptions } from './BookNodeAgentSource';
|
|
2
|
+
import { CLI_AGENT_HARNESS_NAMES, CLI_AGENT_THINKING_LEVEL_VALUES } from './cliAgentEnv';
|
|
2
3
|
/**
|
|
3
4
|
* CLI harness names supported by `ptbk agent exec`.
|
|
4
5
|
*
|
|
5
6
|
* @public exported from `@promptbook/node`
|
|
6
7
|
*/
|
|
7
|
-
export type CliAgentHarness =
|
|
8
|
+
export type CliAgentHarness = (typeof CLI_AGENT_HARNESS_NAMES)[number];
|
|
8
9
|
/**
|
|
9
10
|
* Thinking levels supported by CLI coding harnesses.
|
|
10
11
|
*
|
|
11
12
|
* @public exported from `@promptbook/node`
|
|
12
13
|
*/
|
|
13
|
-
export type CliAgentThinkingLevel =
|
|
14
|
+
export type CliAgentThinkingLevel = (typeof CLI_AGENT_THINKING_LEVEL_VALUES)[number];
|
|
14
15
|
/**
|
|
15
16
|
* Per-run CLI options exposed by `CliAgent`.
|
|
16
17
|
*
|
|
@@ -22,6 +23,7 @@ export type CliAgentRunOptions = {
|
|
|
22
23
|
readonly allowCredits?: boolean;
|
|
23
24
|
readonly context?: string;
|
|
24
25
|
readonly harness?: CliAgentHarness;
|
|
26
|
+
readonly isVerbose?: boolean;
|
|
25
27
|
readonly model?: string;
|
|
26
28
|
readonly noUi?: boolean;
|
|
27
29
|
readonly thinkingLevel?: CliAgentThinkingLevel;
|
|
@@ -38,6 +40,9 @@ export type CliAgentOptions = BookNodeAgentSourceOptions & CliAgentRunOptions;
|
|
|
38
40
|
* It uses the same harnesses and execution path as `ptbk agent exec`, running the runner
|
|
39
41
|
* in-process instead of spawning a separate CLI process.
|
|
40
42
|
*
|
|
43
|
+
* When no `harness` is provided in the constructor or per-run options, `CliAgent` falls back
|
|
44
|
+
* to the `PTBK_HARNESS` environment variable, mirroring `ptbk agent exec` behavior.
|
|
45
|
+
*
|
|
41
46
|
* @public exported from `@promptbook/node`
|
|
42
47
|
*/
|
|
43
48
|
export declare class CliAgent {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* All CLI harness names supported by `CliAgent` and `ptbk agent exec`.
|
|
3
|
+
*
|
|
4
|
+
* @public exported from `@promptbook/node`
|
|
5
|
+
*/
|
|
6
|
+
export declare const CLI_AGENT_HARNESS_NAMES: readonly ["openai-codex", "github-copilot", "cline", "claude-code", "opencode", "gemini"];
|
|
7
|
+
/**
|
|
8
|
+
* All supported thinking-level values for CLI coding-agent runners.
|
|
9
|
+
*
|
|
10
|
+
* @public exported from `@promptbook/node`
|
|
11
|
+
*/
|
|
12
|
+
export declare const CLI_AGENT_THINKING_LEVEL_VALUES: readonly ["low", "medium", "high", "xhigh"];
|
|
13
|
+
/**
|
|
14
|
+
* Environment variable used as the default runner identifier when `--harness` is omitted or not set in `CliAgent`.
|
|
15
|
+
*
|
|
16
|
+
* Set this to one of the harness names (`openai-codex`, `github-copilot`, `cline`, `claude-code`, `opencode`, `gemini`)
|
|
17
|
+
* so that `CliAgent` and `ptbk agent exec` can run without an explicit `harness` option.
|
|
18
|
+
*
|
|
19
|
+
* @public exported from `@promptbook/node`
|
|
20
|
+
*/
|
|
21
|
+
export declare const PTBK_HARNESS_ENV = "PTBK_HARNESS";
|
|
22
|
+
/**
|
|
23
|
+
* Environment variable used as the default runner model when `--model` is omitted or not set in `CliAgent`.
|
|
24
|
+
*
|
|
25
|
+
* @public exported from `@promptbook/node`
|
|
26
|
+
*/
|
|
27
|
+
export declare const PTBK_MODEL_ENV = "PTBK_MODEL";
|
|
28
|
+
/**
|
|
29
|
+
* Environment variable used as the default thinking level when `--thinking-level` is omitted or not set in `CliAgent`.
|
|
30
|
+
*
|
|
31
|
+
* @public exported from `@promptbook/node`
|
|
32
|
+
*/
|
|
33
|
+
export declare const PTBK_THINKING_LEVEL_ENV = "PTBK_THINKING_LEVEL";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CSSProperties } from 'react';
|
|
1
|
+
import { type CSSProperties } from 'react';
|
|
2
2
|
import type { Promisable } from 'type-fest';
|
|
3
3
|
import type { string_book } from '../../book-2.0/agent-source/string_book';
|
|
4
4
|
import type { number_percent } from '../../types/number_percent';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Props for the citation iframe preview component.
|
|
3
|
+
*
|
|
4
|
+
* @private component of `<ChatCitationModal/>`
|
|
5
|
+
*/
|
|
6
|
+
export type CitationIframePreviewProps = {
|
|
7
|
+
src: string;
|
|
8
|
+
title: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Renders a citation URL preview as an iframe when the target page allows embedding,
|
|
12
|
+
* or falls back to a server-side screenshot with an "Open in new tab" link when it
|
|
13
|
+
* does not (e.g. X-Frame-Options: DENY / SAMEORIGIN).
|
|
14
|
+
*
|
|
15
|
+
* Embedding capability is determined by `GET /api/page-preview/check?url=<url>`.
|
|
16
|
+
* If that endpoint is unavailable the component falls back to the iframe directly.
|
|
17
|
+
*
|
|
18
|
+
* @private component of `<ChatCitationModal/>`
|
|
19
|
+
*/
|
|
20
|
+
export declare function CitationIframePreview({ src, title }: CitationIframePreviewProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,29 +1,13 @@
|
|
|
1
1
|
import { Command as Program } from 'commander';
|
|
2
2
|
import type { ThinkingLevel } from '../coder/ThinkingLevel';
|
|
3
|
+
import { PTBK_HARNESS_ENV, PTBK_MODEL_ENV, PTBK_THINKING_LEVEL_ENV } from '../../../book-3.0/cliAgentEnv';
|
|
4
|
+
export { PTBK_HARNESS_ENV, PTBK_MODEL_ENV, PTBK_THINKING_LEVEL_ENV };
|
|
3
5
|
/**
|
|
4
6
|
* Runner identifiers supported by Promptbook CLI agent orchestration commands.
|
|
5
7
|
*
|
|
6
8
|
* @private internal utility of `promptbookCli`
|
|
7
9
|
*/
|
|
8
10
|
export declare const PROMPT_RUNNER_HARNESS_NAMES: readonly ["openai-codex", "github-copilot", "cline", "claude-code", "opencode", "gemini"];
|
|
9
|
-
/**
|
|
10
|
-
* Environment variable used as the default runner identifier when `--harness` is omitted.
|
|
11
|
-
*
|
|
12
|
-
* @private internal utility of `promptbookCli`
|
|
13
|
-
*/
|
|
14
|
-
export declare const PTBK_HARNESS_ENV = "PTBK_HARNESS";
|
|
15
|
-
/**
|
|
16
|
-
* Environment variable used as the default runner model when `--model` is omitted.
|
|
17
|
-
*
|
|
18
|
-
* @private internal utility of `promptbookCli`
|
|
19
|
-
*/
|
|
20
|
-
export declare const PTBK_MODEL_ENV = "PTBK_MODEL";
|
|
21
|
-
/**
|
|
22
|
-
* Environment variable used as the default runner thinking level when `--thinking-level` is omitted.
|
|
23
|
-
*
|
|
24
|
-
* @private internal utility of `promptbookCli`
|
|
25
|
-
*/
|
|
26
|
-
export declare const PTBK_THINKING_LEVEL_ENV = "PTBK_THINKING_LEVEL";
|
|
27
11
|
/**
|
|
28
12
|
* Runner identifier supported by Promptbook CLI agent orchestration commands.
|
|
29
13
|
*
|
package/esm/src/version.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
|
|
|
15
15
|
export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
|
|
16
16
|
/**
|
|
17
17
|
* Represents the version string of the Promptbook engine.
|
|
18
|
-
* It follows semantic versioning (e.g., `0.112.0-
|
|
18
|
+
* It follows semantic versioning (e.g., `0.112.0-118`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptbook/browser",
|
|
3
|
-
"version": "0.112.0-
|
|
3
|
+
"version": "0.112.0-119",
|
|
4
4
|
"description": "Promptbook: Create persistent AI agents that turn your company's scattered knowledge into action",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"types": "./esm/src/_packages/browser.index.d.ts",
|
|
99
99
|
"typings": "./esm/src/_packages/browser.index.d.ts",
|
|
100
100
|
"peerDependencies": {
|
|
101
|
-
"@promptbook/core": "0.112.0-
|
|
101
|
+
"@promptbook/core": "0.112.0-119"
|
|
102
102
|
},
|
|
103
103
|
"dependencies": {
|
|
104
104
|
"@openai/agents": "0.4.15",
|
package/umd/index.umd.js
CHANGED
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* @generated
|
|
30
30
|
* @see https://github.com/webgptorg/promptbook
|
|
31
31
|
*/
|
|
32
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-
|
|
32
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.112.0-119';
|
|
33
33
|
/**
|
|
34
34
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
35
35
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -6161,21 +6161,22 @@
|
|
|
6161
6161
|
* @private helper of `fractalAvatarVisual`
|
|
6162
6162
|
*/
|
|
6163
6163
|
function drawDragonCurveLayer(context, points, options) {
|
|
6164
|
-
const {
|
|
6164
|
+
const { primaryColor, secondaryColor, tertiaryColor, shadowColor, strokeWidth, timeMs, layerIndex } = options;
|
|
6165
6165
|
const firstPoint = points[0];
|
|
6166
6166
|
const lastPoint = points[points.length - 1];
|
|
6167
6167
|
const ribbonGradient = context.createLinearGradient(firstPoint.x, firstPoint.y, lastPoint.x, lastPoint.y);
|
|
6168
6168
|
ribbonGradient.addColorStop(0, `${primaryColor}f2`);
|
|
6169
6169
|
ribbonGradient.addColorStop(0.5, `${secondaryColor}e6`);
|
|
6170
6170
|
ribbonGradient.addColorStop(1, `${tertiaryColor}f2`);
|
|
6171
|
+
// Approximate the blurred shadow stroke with a wider semi-transparent stroke instead of
|
|
6172
|
+
// context.filter blur, which triggers a costly software rasterization pass every frame.
|
|
6171
6173
|
context.save();
|
|
6172
6174
|
context.beginPath();
|
|
6173
6175
|
tracePolyline(context, points);
|
|
6174
|
-
context.strokeStyle = `${shadowColor}
|
|
6175
|
-
context.lineWidth = strokeWidth *
|
|
6176
|
+
context.strokeStyle = `${shadowColor}48`;
|
|
6177
|
+
context.lineWidth = strokeWidth * 4.5;
|
|
6176
6178
|
context.lineJoin = 'round';
|
|
6177
6179
|
context.lineCap = 'round';
|
|
6178
|
-
context.filter = `blur(${size * 0.022}px)`;
|
|
6179
6180
|
context.stroke();
|
|
6180
6181
|
context.restore();
|
|
6181
6182
|
context.beginPath();
|
|
@@ -6759,11 +6760,23 @@
|
|
|
6759
6760
|
* @private helper of `minecraft2AvatarVisual`
|
|
6760
6761
|
*/
|
|
6761
6762
|
function drawMinecraftShadow(context, size, palette, interaction, timeMs) {
|
|
6763
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.03;
|
|
6764
|
+
const cy = size * 0.85 + Math.sin(timeMs / 880) * size * 0.01;
|
|
6765
|
+
const rx = size * (0.16 + interaction.intensity * 0.015);
|
|
6766
|
+
const ry = size * 0.055;
|
|
6767
|
+
// Radial gradient approximates the blurry ellipse shadow without context.filter blur.
|
|
6762
6768
|
context.save();
|
|
6763
|
-
context.
|
|
6764
|
-
context.
|
|
6769
|
+
context.translate(cx, cy);
|
|
6770
|
+
context.scale(1, ry / rx);
|
|
6771
|
+
const blurRadius = rx * 1.4;
|
|
6772
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
6773
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
6774
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
6775
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
6776
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
6777
|
+
context.fillStyle = shadowGradient;
|
|
6765
6778
|
context.beginPath();
|
|
6766
|
-
context.
|
|
6779
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
6767
6780
|
context.fill();
|
|
6768
6781
|
context.restore();
|
|
6769
6782
|
}
|
|
@@ -6987,13 +7000,27 @@
|
|
|
6987
7000
|
spotlight.addColorStop(1, `${palette.highlight}00`);
|
|
6988
7001
|
context.fillStyle = spotlight;
|
|
6989
7002
|
context.fillRect(0, 0, size, size);
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
7003
|
+
{
|
|
7004
|
+
// Radial gradient approximates the blurry ellipse shadow without context.filter blur.
|
|
7005
|
+
const cx = size * 0.5;
|
|
7006
|
+
const cy = size * 0.86;
|
|
7007
|
+
const rx = size * 0.2;
|
|
7008
|
+
const ry = size * 0.06;
|
|
7009
|
+
const blurRadius = rx * 1.4;
|
|
7010
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
7011
|
+
shadowGradient.addColorStop(0, 'rgba(0,0,0,0.28)');
|
|
7012
|
+
shadowGradient.addColorStop(0.45, 'rgba(0,0,0,0.14)');
|
|
7013
|
+
shadowGradient.addColorStop(0.8, 'rgba(0,0,0,0.05)');
|
|
7014
|
+
shadowGradient.addColorStop(1, 'rgba(0,0,0,0)');
|
|
7015
|
+
context.save();
|
|
7016
|
+
context.translate(cx, cy);
|
|
7017
|
+
context.scale(1, ry / rx);
|
|
7018
|
+
context.fillStyle = shadowGradient;
|
|
7019
|
+
context.beginPath();
|
|
7020
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
7021
|
+
context.fill();
|
|
7022
|
+
context.restore();
|
|
7023
|
+
}
|
|
6997
7024
|
drawVoxelCuboid(context, {
|
|
6998
7025
|
x: bodyX,
|
|
6999
7026
|
y: bodyY,
|
|
@@ -8045,6 +8072,35 @@
|
|
|
8045
8072
|
y: -0.62,
|
|
8046
8073
|
z: 0.94,
|
|
8047
8074
|
});
|
|
8075
|
+
/**
|
|
8076
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
8077
|
+
*
|
|
8078
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
8079
|
+
*/
|
|
8080
|
+
const octopus3dStableStateCache = new WeakMap();
|
|
8081
|
+
/**
|
|
8082
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
8083
|
+
*
|
|
8084
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
8085
|
+
*/
|
|
8086
|
+
function getOctopus3dStableState(createRandom) {
|
|
8087
|
+
const cached = octopus3dStableStateCache.get(createRandom);
|
|
8088
|
+
if (cached !== undefined) {
|
|
8089
|
+
return cached;
|
|
8090
|
+
}
|
|
8091
|
+
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
8092
|
+
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
8093
|
+
const leftEyePhaseOffset = eyeRandom() * 0.6;
|
|
8094
|
+
const rightEyePhaseOffset = eyeRandom() * 0.6;
|
|
8095
|
+
const state = {
|
|
8096
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
8097
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
8098
|
+
leftEyePhaseOffset,
|
|
8099
|
+
rightEyePhaseOffset,
|
|
8100
|
+
};
|
|
8101
|
+
octopus3dStableStateCache.set(createRandom, state);
|
|
8102
|
+
return state;
|
|
8103
|
+
}
|
|
8048
8104
|
/**
|
|
8049
8105
|
* Proper 3D Octopus visual built from projected organic meshes and tentacles.
|
|
8050
8106
|
*
|
|
@@ -8057,10 +8113,7 @@
|
|
|
8057
8113
|
isAnimated: true,
|
|
8058
8114
|
supportsPointerTracking: true,
|
|
8059
8115
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
8060
|
-
const morphologyProfile =
|
|
8061
|
-
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
8062
|
-
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
8063
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
8116
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3dStableState(createRandom);
|
|
8064
8117
|
const sceneCenterX = size * 0.5;
|
|
8065
8118
|
const sceneCenterY = size * 0.56;
|
|
8066
8119
|
const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
|
|
@@ -8157,12 +8210,12 @@
|
|
|
8157
8210
|
x: -faceEyeSpacing,
|
|
8158
8211
|
y: faceEyeYOffset,
|
|
8159
8212
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, -faceEyeSpacing, faceEyeYOffset),
|
|
8160
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase +
|
|
8213
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
8161
8214
|
drawProjectedOrganicEye(context, {
|
|
8162
8215
|
x: faceEyeSpacing,
|
|
8163
8216
|
y: faceEyeYOffset,
|
|
8164
8217
|
z: resolveEllipsoidSurfaceDepth(mantleRadiusX, mantleRadiusY, mantleRadiusZ, faceEyeSpacing, faceEyeYOffset),
|
|
8165
|
-
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 +
|
|
8218
|
+
}, faceEyeRadiusX, faceEyeRadiusY, mantleCenter, headPitch, headYaw, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.7 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
8166
8219
|
drawProjectedOrganicMouth(context, [
|
|
8167
8220
|
{
|
|
8168
8221
|
x: -mouthHalfWidth,
|
|
@@ -8206,14 +8259,28 @@
|
|
|
8206
8259
|
/**
|
|
8207
8260
|
* Draws the soft ground shadow below the octopus.
|
|
8208
8261
|
*
|
|
8262
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
8263
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
8264
|
+
*
|
|
8209
8265
|
* @private helper of `octopus3dAvatarVisual`
|
|
8210
8266
|
*/
|
|
8211
8267
|
function drawOctopus3dShadow(context, size, palette, interaction, timeMs) {
|
|
8268
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.04;
|
|
8269
|
+
const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
|
|
8270
|
+
const rx = size * (0.18 + interaction.intensity * 0.02);
|
|
8271
|
+
const ry = size * 0.06;
|
|
8212
8272
|
context.save();
|
|
8213
|
-
context.
|
|
8214
|
-
context.
|
|
8273
|
+
context.translate(cx, cy);
|
|
8274
|
+
context.scale(1, ry / rx);
|
|
8275
|
+
const blurRadius = rx * 1.4;
|
|
8276
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
8277
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
8278
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
8279
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
8280
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
8281
|
+
context.fillStyle = shadowGradient;
|
|
8215
8282
|
context.beginPath();
|
|
8216
|
-
context.
|
|
8283
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
8217
8284
|
context.fill();
|
|
8218
8285
|
context.restore();
|
|
8219
8286
|
}
|
|
@@ -8444,6 +8511,35 @@
|
|
|
8444
8511
|
y: -0.6,
|
|
8445
8512
|
z: 0.98,
|
|
8446
8513
|
});
|
|
8514
|
+
/**
|
|
8515
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
8516
|
+
*
|
|
8517
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8518
|
+
*/
|
|
8519
|
+
const octopus3d2StableStateCache = new WeakMap();
|
|
8520
|
+
/**
|
|
8521
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
8522
|
+
*
|
|
8523
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
8524
|
+
*/
|
|
8525
|
+
function getOctopus3d2StableState(createRandom) {
|
|
8526
|
+
const cached = octopus3d2StableStateCache.get(createRandom);
|
|
8527
|
+
if (cached !== undefined) {
|
|
8528
|
+
return cached;
|
|
8529
|
+
}
|
|
8530
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
8531
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
8532
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
8533
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
8534
|
+
const state = {
|
|
8535
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
8536
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
8537
|
+
leftEyePhaseOffset,
|
|
8538
|
+
rightEyePhaseOffset,
|
|
8539
|
+
};
|
|
8540
|
+
octopus3d2StableStateCache.set(createRandom, state);
|
|
8541
|
+
return state;
|
|
8542
|
+
}
|
|
8447
8543
|
/**
|
|
8448
8544
|
* Octopus 3D 2 avatar visual.
|
|
8449
8545
|
*
|
|
@@ -8456,10 +8552,7 @@
|
|
|
8456
8552
|
isAnimated: true,
|
|
8457
8553
|
supportsPointerTracking: true,
|
|
8458
8554
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
8459
|
-
const morphologyProfile =
|
|
8460
|
-
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
8461
|
-
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
8462
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
8555
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } = getOctopus3d2StableState(createRandom);
|
|
8463
8556
|
const sceneCenterX = size * 0.5;
|
|
8464
8557
|
const sceneCenterY = size * 0.575;
|
|
8465
8558
|
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
@@ -8512,8 +8605,8 @@
|
|
|
8512
8605
|
const rightEyeLocalCenter = sampleBlobbyOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude);
|
|
8513
8606
|
const eyeRadiusX = size * morphologyProfile.face.eyeRadiusXRatio * 0.78;
|
|
8514
8607
|
const eyeRadiusY = eyeRadiusX * morphologyProfile.face.eyeHeightRatio * 0.92;
|
|
8515
|
-
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase +
|
|
8516
|
-
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 +
|
|
8608
|
+
drawProjectedOrganicEye(context, leftEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
8609
|
+
drawProjectedOrganicEye(context, rightEyeLocalCenter, eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.9 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
8517
8610
|
drawProjectedOrganicMouth(context, [
|
|
8518
8611
|
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
8519
8612
|
sampleBlobbyOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
@@ -8542,14 +8635,28 @@
|
|
|
8542
8635
|
/**
|
|
8543
8636
|
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
8544
8637
|
*
|
|
8638
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
8639
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
8640
|
+
*
|
|
8545
8641
|
* @private helper of `octopus3d2AvatarVisual`
|
|
8546
8642
|
*/
|
|
8547
8643
|
function drawBlobbyOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
8644
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
8645
|
+
const cy = size * 0.88 + Math.sin(timeMs / 940) * size * 0.008;
|
|
8646
|
+
const rx = size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018);
|
|
8647
|
+
const ry = size * 0.062;
|
|
8548
8648
|
context.save();
|
|
8549
|
-
context.
|
|
8550
|
-
context.
|
|
8649
|
+
context.translate(cx, cy);
|
|
8650
|
+
context.scale(1, ry / rx);
|
|
8651
|
+
const blurRadius = rx * 1.4;
|
|
8652
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
8653
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
8654
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
8655
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
8656
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
8657
|
+
context.fillStyle = shadowGradient;
|
|
8551
8658
|
context.beginPath();
|
|
8552
|
-
context.
|
|
8659
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
8553
8660
|
context.fill();
|
|
8554
8661
|
context.restore();
|
|
8555
8662
|
}
|
|
@@ -8705,6 +8812,40 @@
|
|
|
8705
8812
|
* @private helper of `octopus3d3AvatarVisual`
|
|
8706
8813
|
*/
|
|
8707
8814
|
const OCTOPUS_TENTACLE_COUNT = 8;
|
|
8815
|
+
/**
|
|
8816
|
+
* Cache keyed by the `createRandom` factory reference, which is stable for the lifetime of one
|
|
8817
|
+
* mounted `<Avatar/>` component (created inside `resolveAvatarRenderDefinition` and held in a
|
|
8818
|
+
* React `useMemo`). Using a `WeakMap` ensures the entry is collected when the component unmounts.
|
|
8819
|
+
*
|
|
8820
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
8821
|
+
*/
|
|
8822
|
+
const stableStateCache = new WeakMap();
|
|
8823
|
+
/**
|
|
8824
|
+
* Returns the stable per-avatar state, computing it on first access and returning the cached
|
|
8825
|
+
* result on every subsequent call within the same `<Avatar/>` mount.
|
|
8826
|
+
*
|
|
8827
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
8828
|
+
*/
|
|
8829
|
+
function getOctopus3d3StableState(createRandom) {
|
|
8830
|
+
const cached = stableStateCache.get(createRandom);
|
|
8831
|
+
if (cached !== undefined) {
|
|
8832
|
+
return cached;
|
|
8833
|
+
}
|
|
8834
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
8835
|
+
const animationRandom = createRandom('octopus3d3-animation-profile');
|
|
8836
|
+
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
8837
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
8838
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
8839
|
+
const state = {
|
|
8840
|
+
morphologyProfile,
|
|
8841
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
8842
|
+
leftEyePhaseOffset,
|
|
8843
|
+
rightEyePhaseOffset,
|
|
8844
|
+
tentacleProfiles: createContinuousTentacleProfiles(createRandom, morphologyProfile),
|
|
8845
|
+
};
|
|
8846
|
+
stableStateCache.set(createRandom, state);
|
|
8847
|
+
return state;
|
|
8848
|
+
}
|
|
8708
8849
|
/**
|
|
8709
8850
|
* Octopus 3D 3 avatar visual.
|
|
8710
8851
|
*
|
|
@@ -8717,11 +8858,7 @@
|
|
|
8717
8858
|
isAnimated: true,
|
|
8718
8859
|
supportsPointerTracking: true,
|
|
8719
8860
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
8720
|
-
const morphologyProfile =
|
|
8721
|
-
const animationRandom = createRandom('octopus3d3-animation-profile');
|
|
8722
|
-
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
8723
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
8724
|
-
const tentacleProfiles = createContinuousTentacleProfiles(createRandom, morphologyProfile);
|
|
8861
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles } = getOctopus3d3StableState(createRandom);
|
|
8725
8862
|
const sceneCenterX = size * 0.5;
|
|
8726
8863
|
const sceneCenterY = size * 0.535;
|
|
8727
8864
|
const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
|
|
@@ -8798,8 +8935,8 @@
|
|
|
8798
8935
|
size,
|
|
8799
8936
|
palette,
|
|
8800
8937
|
});
|
|
8801
|
-
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase +
|
|
8802
|
-
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 +
|
|
8938
|
+
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, -eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + leftEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
8939
|
+
drawProjectedOrganicEye(context, sampleContinuousOctopusSurfacePoint(surfaceOptions, eyeLatitude, eyeLongitude), eyeRadiusX, eyeRadiusY, meshCenter, rotationX, rotationY, sceneCenterX, sceneCenterY, size, palette, timeMs, animationPhase + 0.85 + rightEyePhaseOffset, interaction, morphologyProfile.face.eyeStyle);
|
|
8803
8940
|
drawProjectedOrganicMouth(context, [
|
|
8804
8941
|
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthLatitude, mouthCenterLongitude - mouthHalfLongitude),
|
|
8805
8942
|
sampleContinuousOctopusSurfacePoint(surfaceOptions, mouthCurveLatitude, mouthCenterLongitude),
|
|
@@ -8850,14 +8987,30 @@
|
|
|
8850
8987
|
/**
|
|
8851
8988
|
* Draws the soft lower shadow that anchors the octopus in the avatar frame.
|
|
8852
8989
|
*
|
|
8990
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
8991
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
8992
|
+
*
|
|
8853
8993
|
* @private helper of `octopus3d3AvatarVisual`
|
|
8854
8994
|
*/
|
|
8855
8995
|
function drawContinuousOctopusShadow(context, size, palette, interaction, timeMs, morphologyProfile) {
|
|
8996
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
8997
|
+
const cy = size * 0.9 + Math.sin(timeMs / 980) * size * 0.007;
|
|
8998
|
+
const rx = size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02);
|
|
8999
|
+
const ry = size * 0.06;
|
|
9000
|
+
// Scale the context so that drawing a circle produces the correct ellipse aspect ratio,
|
|
9001
|
+
// then fill with a radial gradient that approximates the blurry edge without context.filter.
|
|
8856
9002
|
context.save();
|
|
8857
|
-
context.
|
|
8858
|
-
context.
|
|
9003
|
+
context.translate(cx, cy);
|
|
9004
|
+
context.scale(1, ry / rx);
|
|
9005
|
+
const blurRadius = rx * 1.4;
|
|
9006
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
9007
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
9008
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
9009
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
9010
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
9011
|
+
context.fillStyle = shadowGradient;
|
|
8859
9012
|
context.beginPath();
|
|
8860
|
-
context.
|
|
9013
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
8861
9014
|
context.fill();
|
|
8862
9015
|
context.restore();
|
|
8863
9016
|
}
|
|
@@ -33277,7 +33430,7 @@
|
|
|
33277
33430
|
return { skippedReason: 'invalid_data_url' };
|
|
33278
33431
|
}
|
|
33279
33432
|
return {
|
|
33280
|
-
file: new File([parsed.buffer], parsed.filename, {
|
|
33433
|
+
file: new File([new Uint8Array(parsed.buffer)], parsed.filename, {
|
|
33281
33434
|
type: parsed.mimeType,
|
|
33282
33435
|
}),
|
|
33283
33436
|
sizeBytes: parsed.buffer.length,
|