@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
|
@@ -55,6 +55,53 @@ const LIGHT_DIRECTION: Point3D = normalizeVector3({
|
|
|
55
55
|
z: 0.98,
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Per-avatar stable state derived once from the seeded random factory and reused across frames.
|
|
60
|
+
*
|
|
61
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
62
|
+
*/
|
|
63
|
+
type Octopus3d2StableState = {
|
|
64
|
+
readonly morphologyProfile: Octopus3MorphologyProfile;
|
|
65
|
+
readonly animationPhase: number;
|
|
66
|
+
readonly leftEyePhaseOffset: number;
|
|
67
|
+
readonly rightEyePhaseOffset: number;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
72
|
+
*
|
|
73
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
74
|
+
*/
|
|
75
|
+
const octopus3d2StableStateCache = new WeakMap<(salt: string) => () => number, Octopus3d2StableState>();
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
79
|
+
*
|
|
80
|
+
* @private helper of `octopus3d2AvatarVisual`
|
|
81
|
+
*/
|
|
82
|
+
function getOctopus3d2StableState(createRandom: (salt: string) => () => number): Octopus3d2StableState {
|
|
83
|
+
const cached = octopus3d2StableStateCache.get(createRandom);
|
|
84
|
+
|
|
85
|
+
if (cached !== undefined) {
|
|
86
|
+
return cached;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const animationRandom = createRandom('octopus3d2-animation-profile');
|
|
90
|
+
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
91
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
92
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
93
|
+
const state: Octopus3d2StableState = {
|
|
94
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
95
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
96
|
+
leftEyePhaseOffset,
|
|
97
|
+
rightEyePhaseOffset,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
octopus3d2StableStateCache.set(createRandom, state);
|
|
101
|
+
|
|
102
|
+
return state;
|
|
103
|
+
}
|
|
104
|
+
|
|
58
105
|
/**
|
|
59
106
|
* Octopus 3D 2 avatar visual.
|
|
60
107
|
*
|
|
@@ -67,10 +114,8 @@ export const octopus3d2AvatarVisual: AvatarVisualDefinition = {
|
|
|
67
114
|
isAnimated: true,
|
|
68
115
|
supportsPointerTracking: true,
|
|
69
116
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
70
|
-
const morphologyProfile =
|
|
71
|
-
|
|
72
|
-
const eyeRandom = createRandom('octopus3d2-eye-profile');
|
|
73
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
117
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } =
|
|
118
|
+
getOctopus3d2StableState(createRandom);
|
|
74
119
|
const sceneCenterX = size * 0.5;
|
|
75
120
|
const sceneCenterY = size * 0.575;
|
|
76
121
|
const bob = Math.sin(timeMs / 940 + animationPhase) * size * 0.013;
|
|
@@ -152,7 +197,7 @@ export const octopus3d2AvatarVisual: AvatarVisualDefinition = {
|
|
|
152
197
|
size,
|
|
153
198
|
palette,
|
|
154
199
|
timeMs,
|
|
155
|
-
animationPhase +
|
|
200
|
+
animationPhase + leftEyePhaseOffset,
|
|
156
201
|
interaction,
|
|
157
202
|
morphologyProfile.face.eyeStyle,
|
|
158
203
|
);
|
|
@@ -169,7 +214,7 @@ export const octopus3d2AvatarVisual: AvatarVisualDefinition = {
|
|
|
169
214
|
size,
|
|
170
215
|
palette,
|
|
171
216
|
timeMs,
|
|
172
|
-
animationPhase + 0.9 +
|
|
217
|
+
animationPhase + 0.9 + rightEyePhaseOffset,
|
|
173
218
|
interaction,
|
|
174
219
|
morphologyProfile.face.eyeStyle,
|
|
175
220
|
);
|
|
@@ -249,6 +294,9 @@ function drawBlobbyOctopusAtmosphere(
|
|
|
249
294
|
/**
|
|
250
295
|
* Draws the soft floor shadow that anchors the single mesh in the frame.
|
|
251
296
|
*
|
|
297
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
298
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
299
|
+
*
|
|
252
300
|
* @private helper of `octopus3d2AvatarVisual`
|
|
253
301
|
*/
|
|
254
302
|
function drawBlobbyOctopusShadow(
|
|
@@ -262,19 +310,23 @@ function drawBlobbyOctopusShadow(
|
|
|
262
310
|
timeMs: number,
|
|
263
311
|
morphologyProfile: Octopus3MorphologyProfile,
|
|
264
312
|
): void {
|
|
313
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
314
|
+
const cy = size * 0.88 + Math.sin(timeMs / 940) * size * 0.008;
|
|
315
|
+
const rx = size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018);
|
|
316
|
+
const ry = size * 0.062;
|
|
317
|
+
|
|
265
318
|
context.save();
|
|
266
|
-
context.
|
|
267
|
-
context.
|
|
319
|
+
context.translate(cx, cy);
|
|
320
|
+
context.scale(1, ry / rx);
|
|
321
|
+
const blurRadius = rx * 1.4;
|
|
322
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
323
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
324
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
325
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
326
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
327
|
+
context.fillStyle = shadowGradient;
|
|
268
328
|
context.beginPath();
|
|
269
|
-
context.
|
|
270
|
-
size * 0.5 + interaction.gazeX * size * 0.045,
|
|
271
|
-
size * 0.88 + Math.sin(timeMs / 940) * size * 0.008,
|
|
272
|
-
size * (0.18 + (morphologyProfile.body.horizontalStretch - 1) * 0.04 + interaction.intensity * 0.018),
|
|
273
|
-
size * 0.062,
|
|
274
|
-
0,
|
|
275
|
-
0,
|
|
276
|
-
Math.PI * 2,
|
|
277
|
-
);
|
|
329
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
278
330
|
context.fill();
|
|
279
331
|
context.restore();
|
|
280
332
|
}
|
|
@@ -93,6 +93,63 @@ const LIGHT_DIRECTION: Point3D = normalizeVector3({
|
|
|
93
93
|
*/
|
|
94
94
|
const OCTOPUS_TENTACLE_COUNT = 8;
|
|
95
95
|
|
|
96
|
+
/**
|
|
97
|
+
* Per-avatar stable state derived once from the seeded random factory and reused across frames.
|
|
98
|
+
*
|
|
99
|
+
* These values depend only on the avatar definition (name + hash + colors) and never change
|
|
100
|
+
* while the avatar is mounted, so computing them once and caching eliminates the largest
|
|
101
|
+
* allocation/computation spike in the hot render path.
|
|
102
|
+
*
|
|
103
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
104
|
+
*/
|
|
105
|
+
type Octopus3d3StableState = {
|
|
106
|
+
readonly morphologyProfile: Octopus3MorphologyProfile;
|
|
107
|
+
readonly animationPhase: number;
|
|
108
|
+
readonly leftEyePhaseOffset: number;
|
|
109
|
+
readonly rightEyePhaseOffset: number;
|
|
110
|
+
readonly tentacleProfiles: ReadonlyArray<ContinuousOctopusTentacleProfile>;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Cache keyed by the `createRandom` factory reference, which is stable for the lifetime of one
|
|
115
|
+
* mounted `<Avatar/>` component (created inside `resolveAvatarRenderDefinition` and held in a
|
|
116
|
+
* React `useMemo`). Using a `WeakMap` ensures the entry is collected when the component unmounts.
|
|
117
|
+
*
|
|
118
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
119
|
+
*/
|
|
120
|
+
const stableStateCache = new WeakMap<(salt: string) => () => number, Octopus3d3StableState>();
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Returns the stable per-avatar state, computing it on first access and returning the cached
|
|
124
|
+
* result on every subsequent call within the same `<Avatar/>` mount.
|
|
125
|
+
*
|
|
126
|
+
* @private helper of `octopus3d3AvatarVisual`
|
|
127
|
+
*/
|
|
128
|
+
function getOctopus3d3StableState(createRandom: (salt: string) => () => number): Octopus3d3StableState {
|
|
129
|
+
const cached = stableStateCache.get(createRandom);
|
|
130
|
+
|
|
131
|
+
if (cached !== undefined) {
|
|
132
|
+
return cached;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const morphologyProfile = createOctopus3MorphologyProfile(createRandom);
|
|
136
|
+
const animationRandom = createRandom('octopus3d3-animation-profile');
|
|
137
|
+
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
138
|
+
const leftEyePhaseOffset = eyeRandom() * 0.7;
|
|
139
|
+
const rightEyePhaseOffset = eyeRandom() * 0.7;
|
|
140
|
+
const state: Octopus3d3StableState = {
|
|
141
|
+
morphologyProfile,
|
|
142
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
143
|
+
leftEyePhaseOffset,
|
|
144
|
+
rightEyePhaseOffset,
|
|
145
|
+
tentacleProfiles: createContinuousTentacleProfiles(createRandom, morphologyProfile),
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
stableStateCache.set(createRandom, state);
|
|
149
|
+
|
|
150
|
+
return state;
|
|
151
|
+
}
|
|
152
|
+
|
|
96
153
|
/**
|
|
97
154
|
* Octopus 3D 3 avatar visual.
|
|
98
155
|
*
|
|
@@ -106,11 +163,8 @@ export const octopus3d3AvatarVisual: AvatarVisualDefinition = {
|
|
|
106
163
|
isAnimated: true,
|
|
107
164
|
supportsPointerTracking: true,
|
|
108
165
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
109
|
-
const morphologyProfile =
|
|
110
|
-
|
|
111
|
-
const eyeRandom = createRandom('octopus3d3-eye-profile');
|
|
112
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
113
|
-
const tentacleProfiles = createContinuousTentacleProfiles(createRandom, morphologyProfile);
|
|
166
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles } =
|
|
167
|
+
getOctopus3d3StableState(createRandom);
|
|
114
168
|
const sceneCenterX = size * 0.5;
|
|
115
169
|
const sceneCenterY = size * 0.535;
|
|
116
170
|
const bob = Math.sin(timeMs / 960 + animationPhase) * size * 0.012;
|
|
@@ -213,7 +267,7 @@ export const octopus3d3AvatarVisual: AvatarVisualDefinition = {
|
|
|
213
267
|
size,
|
|
214
268
|
palette,
|
|
215
269
|
timeMs,
|
|
216
|
-
animationPhase +
|
|
270
|
+
animationPhase + leftEyePhaseOffset,
|
|
217
271
|
interaction,
|
|
218
272
|
morphologyProfile.face.eyeStyle,
|
|
219
273
|
);
|
|
@@ -230,7 +284,7 @@ export const octopus3d3AvatarVisual: AvatarVisualDefinition = {
|
|
|
230
284
|
size,
|
|
231
285
|
palette,
|
|
232
286
|
timeMs,
|
|
233
|
-
animationPhase + 0.85 +
|
|
287
|
+
animationPhase + 0.85 + rightEyePhaseOffset,
|
|
234
288
|
interaction,
|
|
235
289
|
morphologyProfile.face.eyeStyle,
|
|
236
290
|
);
|
|
@@ -338,6 +392,9 @@ function drawContinuousOctopusAtmosphere(
|
|
|
338
392
|
/**
|
|
339
393
|
* Draws the soft lower shadow that anchors the octopus in the avatar frame.
|
|
340
394
|
*
|
|
395
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
396
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
397
|
+
*
|
|
341
398
|
* @private helper of `octopus3d3AvatarVisual`
|
|
342
399
|
*/
|
|
343
400
|
function drawContinuousOctopusShadow(
|
|
@@ -351,19 +408,25 @@ function drawContinuousOctopusShadow(
|
|
|
351
408
|
timeMs: number,
|
|
352
409
|
morphologyProfile: Octopus3MorphologyProfile,
|
|
353
410
|
): void {
|
|
411
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.045;
|
|
412
|
+
const cy = size * 0.9 + Math.sin(timeMs / 980) * size * 0.007;
|
|
413
|
+
const rx = size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02);
|
|
414
|
+
const ry = size * 0.06;
|
|
415
|
+
|
|
416
|
+
// Scale the context so that drawing a circle produces the correct ellipse aspect ratio,
|
|
417
|
+
// then fill with a radial gradient that approximates the blurry edge without context.filter.
|
|
354
418
|
context.save();
|
|
355
|
-
context.
|
|
356
|
-
context.
|
|
419
|
+
context.translate(cx, cy);
|
|
420
|
+
context.scale(1, ry / rx);
|
|
421
|
+
const blurRadius = rx * 1.4;
|
|
422
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
423
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
424
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
425
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
426
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
427
|
+
context.fillStyle = shadowGradient;
|
|
357
428
|
context.beginPath();
|
|
358
|
-
context.
|
|
359
|
-
size * 0.5 + interaction.gazeX * size * 0.045,
|
|
360
|
-
size * 0.9 + Math.sin(timeMs / 980) * size * 0.007,
|
|
361
|
-
size * (0.19 + morphologyProfile.tentacles.rootSpreadScale * 0.022 + interaction.intensity * 0.02),
|
|
362
|
-
size * 0.06,
|
|
363
|
-
0,
|
|
364
|
-
0,
|
|
365
|
-
Math.PI * 2,
|
|
366
|
-
);
|
|
429
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
367
430
|
context.fill();
|
|
368
431
|
context.restore();
|
|
369
432
|
}
|
|
@@ -55,6 +55,53 @@ const LIGHT_DIRECTION: Point3D = normalizeVector3({
|
|
|
55
55
|
z: 0.94,
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* Per-avatar stable state derived once from the seeded random factory and reused across frames.
|
|
60
|
+
*
|
|
61
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
62
|
+
*/
|
|
63
|
+
type Octopus3dStableState = {
|
|
64
|
+
readonly morphologyProfile: Octopus3MorphologyProfile;
|
|
65
|
+
readonly animationPhase: number;
|
|
66
|
+
readonly leftEyePhaseOffset: number;
|
|
67
|
+
readonly rightEyePhaseOffset: number;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Cache keyed by the `createRandom` factory reference (stable per mounted `<Avatar/>`).
|
|
72
|
+
*
|
|
73
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
74
|
+
*/
|
|
75
|
+
const octopus3dStableStateCache = new WeakMap<(salt: string) => () => number, Octopus3dStableState>();
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Returns the stable per-avatar state, computing it on first access and caching for subsequent frames.
|
|
79
|
+
*
|
|
80
|
+
* @private helper of `octopus3dAvatarVisual`
|
|
81
|
+
*/
|
|
82
|
+
function getOctopus3dStableState(createRandom: (salt: string) => () => number): Octopus3dStableState {
|
|
83
|
+
const cached = octopus3dStableStateCache.get(createRandom);
|
|
84
|
+
|
|
85
|
+
if (cached !== undefined) {
|
|
86
|
+
return cached;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const animationRandom = createRandom('octopus3d-animation-profile');
|
|
90
|
+
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
91
|
+
const leftEyePhaseOffset = eyeRandom() * 0.6;
|
|
92
|
+
const rightEyePhaseOffset = eyeRandom() * 0.6;
|
|
93
|
+
const state: Octopus3dStableState = {
|
|
94
|
+
morphologyProfile: createOctopus3MorphologyProfile(createRandom),
|
|
95
|
+
animationPhase: animationRandom() * Math.PI * 2,
|
|
96
|
+
leftEyePhaseOffset,
|
|
97
|
+
rightEyePhaseOffset,
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
octopus3dStableStateCache.set(createRandom, state);
|
|
101
|
+
|
|
102
|
+
return state;
|
|
103
|
+
}
|
|
104
|
+
|
|
58
105
|
/**
|
|
59
106
|
* Proper 3D Octopus visual built from projected organic meshes and tentacles.
|
|
60
107
|
*
|
|
@@ -67,10 +114,8 @@ export const octopus3dAvatarVisual: AvatarVisualDefinition = {
|
|
|
67
114
|
isAnimated: true,
|
|
68
115
|
supportsPointerTracking: true,
|
|
69
116
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
70
|
-
const morphologyProfile =
|
|
71
|
-
|
|
72
|
-
const eyeRandom = createRandom('octopus3d-eye-profile');
|
|
73
|
-
const animationPhase = animationRandom() * Math.PI * 2;
|
|
117
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset } =
|
|
118
|
+
getOctopus3dStableState(createRandom);
|
|
74
119
|
const sceneCenterX = size * 0.5;
|
|
75
120
|
const sceneCenterY = size * 0.56;
|
|
76
121
|
const bob = Math.sin(timeMs / 920 + animationPhase) * size * 0.014;
|
|
@@ -201,7 +246,7 @@ export const octopus3dAvatarVisual: AvatarVisualDefinition = {
|
|
|
201
246
|
size,
|
|
202
247
|
palette,
|
|
203
248
|
timeMs,
|
|
204
|
-
animationPhase +
|
|
249
|
+
animationPhase + leftEyePhaseOffset,
|
|
205
250
|
interaction,
|
|
206
251
|
morphologyProfile.face.eyeStyle,
|
|
207
252
|
);
|
|
@@ -228,7 +273,7 @@ export const octopus3dAvatarVisual: AvatarVisualDefinition = {
|
|
|
228
273
|
size,
|
|
229
274
|
palette,
|
|
230
275
|
timeMs,
|
|
231
|
-
animationPhase + 0.7 +
|
|
276
|
+
animationPhase + 0.7 + rightEyePhaseOffset,
|
|
232
277
|
interaction,
|
|
233
278
|
morphologyProfile.face.eyeStyle,
|
|
234
279
|
);
|
|
@@ -334,6 +379,9 @@ function drawOctopus3dAtmosphere(
|
|
|
334
379
|
/**
|
|
335
380
|
* Draws the soft ground shadow below the octopus.
|
|
336
381
|
*
|
|
382
|
+
* Uses a scaled radial gradient instead of `context.filter = 'blur()'` to approximate the
|
|
383
|
+
* blurry ellipse without triggering a costly software rasterization pass on every frame.
|
|
384
|
+
*
|
|
337
385
|
* @private helper of `octopus3dAvatarVisual`
|
|
338
386
|
*/
|
|
339
387
|
function drawOctopus3dShadow(
|
|
@@ -346,19 +394,23 @@ function drawOctopus3dShadow(
|
|
|
346
394
|
},
|
|
347
395
|
timeMs: number,
|
|
348
396
|
): void {
|
|
397
|
+
const cx = size * 0.5 + interaction.gazeX * size * 0.04;
|
|
398
|
+
const cy = size * 0.87 + Math.sin(timeMs / 920) * size * 0.008;
|
|
399
|
+
const rx = size * (0.18 + interaction.intensity * 0.02);
|
|
400
|
+
const ry = size * 0.06;
|
|
401
|
+
|
|
349
402
|
context.save();
|
|
350
|
-
context.
|
|
351
|
-
context.
|
|
403
|
+
context.translate(cx, cy);
|
|
404
|
+
context.scale(1, ry / rx);
|
|
405
|
+
const blurRadius = rx * 1.4;
|
|
406
|
+
const shadowGradient = context.createRadialGradient(0, 0, 0, 0, 0, blurRadius);
|
|
407
|
+
shadowGradient.addColorStop(0, `${palette.shadow}7a`);
|
|
408
|
+
shadowGradient.addColorStop(0.45, `${palette.shadow}44`);
|
|
409
|
+
shadowGradient.addColorStop(0.8, `${palette.shadow}1a`);
|
|
410
|
+
shadowGradient.addColorStop(1, `${palette.shadow}00`);
|
|
411
|
+
context.fillStyle = shadowGradient;
|
|
352
412
|
context.beginPath();
|
|
353
|
-
context.
|
|
354
|
-
size * 0.5 + interaction.gazeX * size * 0.04,
|
|
355
|
-
size * 0.87 + Math.sin(timeMs / 920) * size * 0.008,
|
|
356
|
-
size * (0.18 + interaction.intensity * 0.02),
|
|
357
|
-
size * 0.06,
|
|
358
|
-
0,
|
|
359
|
-
0,
|
|
360
|
-
Math.PI * 2,
|
|
361
|
-
);
|
|
413
|
+
context.arc(0, 0, blurRadius, 0, Math.PI * 2);
|
|
362
414
|
context.fill();
|
|
363
415
|
context.restore();
|
|
364
416
|
}
|
package/src/book-3.0/Book.ts
CHANGED
|
@@ -215,7 +215,9 @@ function parseBookMessageHeader(line: string): Pick<BookMessageBlock, 'marker' |
|
|
|
215
215
|
* @private internal utility of `Book`
|
|
216
216
|
*/
|
|
217
217
|
function parseCommitmentHeader(line: string): Commitment | null {
|
|
218
|
-
|
|
218
|
+
// Require at least 2 characters in the first keyword word to avoid treating common
|
|
219
|
+
// single-letter words (e.g. "V" in Czech, "I" or "A" in English) as commitment headers.
|
|
220
|
+
const match = /^([A-Z][A-Z0-9]+(?: [A-Z0-9]+)*)(?:\s+(.*))?$/u.exec(line);
|
|
219
221
|
if (!match) {
|
|
220
222
|
return null;
|
|
221
223
|
}
|
|
@@ -23,7 +23,7 @@ export type BookNodeAgentSource = Book | string_book;
|
|
|
23
23
|
*/
|
|
24
24
|
export type BookNodeAgentSourceOptions = {
|
|
25
25
|
readonly agentPath?: string;
|
|
26
|
-
readonly book?: BookNodeAgentSource;
|
|
26
|
+
readonly book?: string | BookNodeAgentSource;
|
|
27
27
|
readonly currentWorkingDirectory?: string;
|
|
28
28
|
};
|
|
29
29
|
|
|
@@ -92,7 +92,7 @@ export async function resolveBookNodeAgentSource(
|
|
|
92
92
|
*
|
|
93
93
|
* @private internal utility of `resolveBookNodeAgentSource`
|
|
94
94
|
*/
|
|
95
|
-
function normalizeBookNodeAgentSource(book: BookNodeAgentSource): string_book {
|
|
95
|
+
function normalizeBookNodeAgentSource(book: string | BookNodeAgentSource): string_book {
|
|
96
96
|
if (book instanceof Book) {
|
|
97
97
|
return book.stringify();
|
|
98
98
|
}
|